diff --git a/.travis.yml b/.travis.yml
index 8197d31..310b7cf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,17 +9,6 @@ cache:
directories:
- node_modules
-env:
- - EMBER_TRY_SCENARIO=default
- - EMBER_TRY_SCENARIO=ember-release
- - EMBER_TRY_SCENARIO=ember-beta
- - EMBER_TRY_SCENARIO=ember-canary
-
-matrix:
- fast_finish: true
- allow_failures:
- - env: EMBER_TRY_SCENARIO=ember-canary
-
before_install:
- export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
- "npm config set spin false"
@@ -31,4 +20,4 @@ install:
- bower install
script:
- - ember try $EMBER_TRY_SCENARIO test
+ - ember try:testall
diff --git a/README.md b/README.md
index 4ddd137..cc1c013 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,25 @@ if you have a model with a `status` field with an integer, you can do this:
{{/x-select}}
```
+### Contextual Components
+
+As of version 2.1.0, `emberx-select` takes advantage of Ember's
+[contextual components](http://emberjs.com/blog/2016/01/15/ember-2-3-released.html#toc_contextual-components)
+feature. Using contextual components allows `emberx-select` to skip some
+potentially expensive DOM traversals. This feature works with **Ember
+2.3.0 and above!** If you're using such a version, we highly recommend
+you use it:
+
+```handlebars
+{{#x-select value=model.status as |xs|}}
+ {{#xs.option value=1}}Active{{/xs.option}}
+ {{#xs.option value=2}}Inactive{{/xs.option}}
+{{/x-select}}
+```
+
+If you're using a lower version of Ember, `emberx-select` will continue
+to work without block params for the forseeable future.
+
### Multiselect
As of version 1.1.0, `emberx-select` supports the `multiple`
diff --git a/addon/components/x-option.js b/addon/components/x-option.js
index 08daedf..1c0105e 100644
--- a/addon/components/x-option.js
+++ b/addon/components/x-option.js
@@ -56,10 +56,13 @@ export default Ember.Component.extend({
Ember.run.scheduleOnce('afterRender', this, 'registerWithXSelect');
},
+ select: Ember.computed(function() {
+ return this.nearestOfType(XSelectComponent);
+ }),
+
registerWithXSelect() {
- var select = this.nearestOfType(XSelectComponent);
+ const select = this.get('select');
Ember.assert("x-option component declared without enclosing x-select", !!select);
- this.set('select', select);
select.registerOption(this);
},
diff --git a/addon/templates/current/components/x-select.hbs b/addon/templates/current/components/x-select.hbs
new file mode 100644
index 0000000..83ee33b
--- /dev/null
+++ b/addon/templates/current/components/x-select.hbs
@@ -0,0 +1,5 @@
+{{yield
+ (hash
+ option=(component "x-option" select=this)
+ )
+}}
diff --git a/app/templates/components/x-select.hbs b/addon/templates/less-than-2.3/components/x-select.hbs
similarity index 100%
rename from app/templates/components/x-select.hbs
rename to addon/templates/less-than-2.3/components/x-select.hbs
diff --git a/app/templates/components/x-select.js b/app/templates/components/x-select.js
new file mode 100644
index 0000000..97a7599
--- /dev/null
+++ b/app/templates/components/x-select.js
@@ -0,0 +1 @@
+export { default } from 'emberx-select/templates/components/x-select';
diff --git a/config/ember-try.js b/config/ember-try.js
index 83dab0f..42c7cfe 100644
--- a/config/ember-try.js
+++ b/config/ember-try.js
@@ -4,6 +4,34 @@ module.exports = {
name: 'default',
dependencies: { }
},
+ {
+ name: 'ember-1-13',
+ dependencies: {
+ "ember": "^1.13",
+ },
+ resolutions: {
+ "ember": "^1.13"
+ }
+ },
+ {
+ // ember 2 before contextual components
+ name: 'ember-2-2',
+ dependencies: {
+ "ember": "~2.2.0",
+ },
+ resolutions: {
+ "ember": "~2.2.0"
+ }
+ },
+ {
+ name: 'ember-2-3',
+ dependencies: {
+ "ember": "~2.3.0",
+ },
+ resolutions: {
+ "ember": "~2.3.0"
+ }
+ },
{
name: 'ember-release',
dependencies: {
diff --git a/index.js b/index.js
index e4a29b1..4c64de5 100644
--- a/index.js
+++ b/index.js
@@ -2,5 +2,29 @@
'use strict';
module.exports = {
- name: 'emberx-select'
+ name: 'emberx-select',
+
+ hasContextualComponents: function () {
+ var VersionChecker = require('ember-cli-version-checker');
+
+ var checker = new VersionChecker(this);
+ var dep = checker.for('ember', 'bower');
+
+ var isBetaOrCanary = ['beta', 'canary'].filter(function(version) {
+ return dep.version.indexOf(version) >= 0;
+ });
+
+ return !!(dep.satisfies('>= 2.3.0 < 3.0.0') || isBetaOrCanary.length > 0);
+ },
+
+ treeForAddonTemplates: function treeForAddonTemplates(tree) {
+ var path = require('path');
+ var baseTemplatesPath = path.join(this.root, 'addon/templates');
+
+ if (this.hasContextualComponents()) {
+ return this.treeGenerator(path.join(baseTemplatesPath, 'current'));
+ } else {
+ return this.treeGenerator(path.join(baseTemplatesPath, 'less-than-2.3'));
+ }
+ }
};
diff --git a/package.json b/package.json
index cf580a1..910e440 100644
--- a/package.json
+++ b/package.json
@@ -19,13 +19,12 @@
"license": "MIT",
"devDependencies": {
"broccoli-asset-rev": "^2.1.2",
- "ember-cli": "1.13.8",
+ "ember-cli": "^1.13.8",
"ember-cli-app-version": "0.5.0",
"ember-cli-content-security-policy": "0.4.0",
"ember-cli-dependency-checker": "^1.0.1",
"ember-cli-github-pages": "0.0.6",
- "ember-cli-htmlbars": "0.7.9",
- "ember-cli-htmlbars-inline-precompile": "^0.2.0",
+ "ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-ic-ajax": "0.2.1",
"ember-cli-inject-live-reload": "^1.3.1",
"ember-cli-mocha": "0.9.8",
@@ -43,7 +42,9 @@
"select"
],
"dependencies": {
- "ember-cli-babel": "^5.1.3"
+ "ember-cli-babel": "^5.1.3",
+ "ember-cli-htmlbars": "^1.0.0",
+ "ember-cli-version-checker": "^1.1.6"
},
"ember-addon": {
"demoURL": "https://thefrontside.github.io/emberx-select",
diff --git a/tests/.jshintrc b/tests/.jshintrc
index d99a486..a4676ff 100644
--- a/tests/.jshintrc
+++ b/tests/.jshintrc
@@ -1,5 +1,6 @@
{
"predef": [
+ "expect",
"document",
"window",
"location",
diff --git a/tests/index.html b/tests/index.html
index 8fea6fe..e0ed521 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -26,6 +26,7 @@
+
{{content-for 'body-footer'}}
{{content-for 'test-body-footer'}}
diff --git a/tests/integration/with-contextual-components/contextual-component-test.js b/tests/integration/with-contextual-components/contextual-component-test.js
new file mode 100644
index 0000000..ee64a92
--- /dev/null
+++ b/tests/integration/with-contextual-components/contextual-component-test.js
@@ -0,0 +1,26 @@
+import { it, describeComponent } from 'ember-mocha';
+import hbs from 'htmlbars-inline-precompile';
+import Ember from 'ember';
+
+const integration = true;
+
+function hasContextualComponents() {
+ return !Ember.VERSION.match(/^2\.[0-2]\./) && !Ember.VERSION.match(/^1/);
+}
+
+describeComponent('x-select', 'X-Select - Contextual Component', {integration}, function() {
+
+ if (hasContextualComponents()) {
+ it('yields a hash with the option component', function() {
+ this.render(hbs`
+ {{#x-select value=status as |xs|}}
+ {{#xs.option value="in the office"}}In the Office{{/xs.option}}
+ {{#xs.option value="out of office"}}Out of Office{{/xs.option}}
+ {{/x-select}}
+ `);
+
+ expect(this.$('option').length).to.equal(2);
+ });
+ }
+});
+