diff --git a/README.md b/README.md index 5ac2b22..60006e9 100644 --- a/README.md +++ b/README.md @@ -105,16 +105,15 @@ Its usage should be very similar to `Ember.Select`, but with additional features optionFunction, itemFunction, optionCreateFunction, optgroupHeaderFunction, optgroupFunction - Will be called on the component with two parameters data and escape. escape is a function to escape text. These functions are expected to build the desired html and return it as a string. These functions take precedence over their Template and View counterparts. + Will be called on the component with two parameters data and escape. escape is a function to escape text. These functions are expected to build the desired html and return it as a string or DOM elements. These functions take precedence over their Component counterparts. - optionTemplate, itemTemplate, optionCreateTemplate, optgroupHeaderTemplate, - optgroupTemplate
optionView, itemView, - optionCreateView, optgroupHeaderView - and optgroupView + optionComponent, itemComponent, + optionCreateComponent, optgroupHeaderComponent + and optgroupComponent - Render using templates or views! View takes precedence over template, so if you do strange things like setting optionView and optionTemplate, the latter will be ignored. Might not work with all Ember versions. This is delicate. Check this issue. + Render using components! Functions (see above) take precedence over components, so if you do strange things like setting optionFunction and optionComponent, the latter will be ignored. Inside your component and template data will contain the data for the current item being rendered. An example component could be Hi, {{data.firstname}}! required diff --git a/addon/components/ember-selectize.js b/addon/components/ember-selectize.js index 084551a..a57bdb1 100644 --- a/addon/components/ember-selectize.js +++ b/addon/components/ember-selectize.js @@ -61,9 +61,8 @@ export default Ember.Component.extend({ var content = this.get('content'); if (!isArray(content)) { return; } - var _this = this; - return content.reduce(function(previousValue, item) { - return previousValue.addObject(get(item, _this.get('_groupPath'))); + return content.reduce((previousValue, item) => { + return previousValue.addObject(get(item, this.get('_groupPath'))); }, Ember.A()); } }), @@ -73,7 +72,6 @@ export default Ember.Component.extend({ */ content: computed('groupedContent.[]', function() { var groupedContent = this.get('groupedContent'); - var _this = this; if (!groupedContent) { return; } @@ -86,7 +84,7 @@ export default Ember.Component.extend({ //set in the object. Use ObjectProxy to keep original object intact. var proxiedContent = content.map(item => { var proxy = { content: item }; - proxy[_this.get('_groupPath')] = groupLabel; + proxy[this.get('_groupPath')] = groupLabel; return Ember.ObjectProxy.create(proxy); }); @@ -105,9 +103,8 @@ export default Ember.Component.extend({ var optgroups = this.get('optgroups'); if (!optgroups) { return; } - var _this = this; optgroups.forEach(group => { - _this._selectize.addOptionGroup(group, { label: group, value: group}); + this._selectize.addOptionGroup(group, { label: group, value: group}); }); }), @@ -144,49 +141,37 @@ export default Ember.Component.extend({ */ functionNames: ['option', 'item', 'option_create', 'optgroup_header', 'optgroup'], templateSuffix: 'Template', - viewSuffix: 'View', + componentSuffix: 'Component', functionSuffix: 'Function', renderOptions: computed(function() { var functionNames = this.get('functionNames'); //this hash will contain the render functions var renderFunctions = {}; - functionNames.forEach(function(item) { + functionNames.forEach(item => { // infer the function name by camelizing selectize's function and appending the function suffix (overridable) var functionSuffix = this.get('functionSuffix'); var functionPropertyName = camelize(item) + functionSuffix; var renderFunction = this.get(functionPropertyName); // functions take precedence if (renderFunction) { - renderFunctions[item] = renderFunction.bind(this.get('targetObject')); + renderFunctions[item] = (data, escape) => { + return renderFunction(data.data || data, escape); + }; } else { // infer the view name by camelizing selectize's function and appending a view suffix (overridable) - var templateSuffix = this.get('templateSuffix'); - var viewSuffix = this.get('viewSuffix'); - var viewPropertyName = camelize(item) + viewSuffix; - var viewToRender = this.get(viewPropertyName); + var componentSuffix = this.get('componentSuffix'); + var componentPropertyName = camelize(item) + componentSuffix; + var componentToRender = this.get(componentPropertyName); - var _this = this; - if (viewToRender) { + if (componentToRender) { // we have a view to render. set the function. - renderFunctions[item] = function(data) { - return _this._viewToString(viewToRender, data.data); + renderFunctions[item] = data => { + return this._componentToDOM(componentToRender, data.data || data); }; - } else { - // there isn't a view to render. try to get a template. - // infer the template name by camelizing selectize's function and appending a template suffix (overridable) - var templatePropertyName = camelize(item) + templateSuffix; - var templateToRender = this.get(templatePropertyName); - - if (templateToRender) { - // we have a template to render. set the function. - renderFunctions[item] = function(data) { - return _this._templateToString(templateToRender, data.data); - }; - } } } - }, this); + }); return renderFunctions; }), @@ -790,46 +775,18 @@ export default Ember.Component.extend({ } }), - _templateToString(templateName, data) { - var template = this.container.lookup('template:' + templateName); - - if (!template) { - throw new TypeError('template ' + templateName + ' does not exist.'); - } - - var controller = Ember.Controller.create(Ember.typeOf(data) === 'instance' ? data : {data: data}); - var view = this.createChildView(Ember.View, { - template: template, - controller: controller, - container: this.get('container') - }); - - return this._getStringFromView(view); - }, - - _viewToString(viewName, data) { - var viewClass = this.container.lookup('view:' + viewName); + _componentToDOM(componentName, data) { + var component = this.container.lookup('component:' + componentName); - if (!viewClass) { - throw new TypeError('view ' + viewName + ' does not exist.'); + if (!component) { + throw new TypeError('component ' + componentName + ' does not exist.'); } - var controller = Ember.Controller.create(Ember.typeOf(data) === 'instance' ? data : {data: data}); - var view = this.createChildView(viewClass, { - controller: controller - }); + component.set('data', data); - return this._getStringFromView(view); - }, + component.createElement(); - /* - * Encapsulates the logic of converting a view to a string - */ - //FIX ME: this method does not work in Ember 1.8.0 - //see http://git.io/VUYZ4g for more info - _getStringFromView(view) { - view.createElement(); - return view.element.outerHTML; + return component.element; }, _mergeSortField(options) { diff --git a/blueprints/ember-cli-selectize/index.js b/blueprints/ember-cli-selectize/index.js index 665a681..22a937f 100644 --- a/blueprints/ember-cli-selectize/index.js +++ b/blueprints/ember-cli-selectize/index.js @@ -6,8 +6,8 @@ module.exports = { // not specified (since that doesn't actually matter // to us }, - + afterInstall: function() { - return this.addBowerPackageToProject('selectize'); + return this.addBowerPackageToProject('selectize', 'miguelcobain/selectize.js#master'); } }; diff --git a/bower.json b/bower.json index 728110c..77bd22b 100644 --- a/bower.json +++ b/bower.json @@ -11,7 +11,7 @@ "jquery": "1.11.3", "loader.js": "ember-cli/loader.js#3.4.0", "qunit": "~1.20.0", - "selectize": "~0.12.0" + "selectize": "miguelcobain/selectize.js#master" }, "resolutions": { "qunit-notifications": "~0.1.0" diff --git a/tests/unit/components/ember-selectize-test.js b/tests/unit/components/ember-selectize-test.js index a65865a..acf7ceb 100644 --- a/tests/unit/components/ember-selectize-test.js +++ b/tests/unit/components/ember-selectize-test.js @@ -3,6 +3,7 @@ import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; moduleForComponent('ember-selectize', 'Unit | Component | ember-selectize', { // Specify the other units that are required for this test @@ -1015,3 +1016,60 @@ test('content from a Promise don\'t overwrite newer content once resolved', func this.render(); }); + +test('renders components', function(assert) { + + //this.register('template:components/foo-bar', hbs`Hi, Mom!`); + this.register('component:foo-bar', Ember.Component.extend({ + layout: hbs`Hi, {{data.firstName}}!` + })); + + + var yehuda = Ember.Object.create({ id: 1, firstName: 'Yehuda' }); + var tom = Ember.Object.create({ id: 2, firstName: 'Tom' }); + var seb = Ember.Object.create({ id: 3, firstName: 'Seb' }); + + var component = this.subject(); + + Ember.run(function() { + component.set('optionComponent', 'foo-bar'); + component.set('optionValuePath', 'id'); + component.set('optionLabelPath', 'firstName'); + component.set('content', Ember.A([yehuda, tom, seb])); + component.set('selection', tom); + }); + + this.render(); + + assert.deepEqual(component._selectize.items, ["2"]); + assert.equal(component._selectize.$dropdown_content.children().length, 3); + assert.equal(component._selectize.$dropdown_content.children().text(), 'Hi, Yehuda!Hi, Tom!Hi, Seb!'); + +}); + +test('renders function', function(assert) { + + var yehuda = Ember.Object.create({ id: 1, firstName: 'Yehuda' }); + var tom = Ember.Object.create({ id: 2, firstName: 'Tom' }); + var seb = Ember.Object.create({ id: 3, firstName: 'Seb' }); + + var component = this.subject(); + + Ember.run(function() { + component.set('optionFunction', function(data) { + assert.equal(arguments.length, 2, 'arguments length'); + return `
Hi, ${data.get('firstName')}!
`; + }); + component.set('optionValuePath', 'id'); + component.set('optionLabelPath', 'firstName'); + component.set('content', Ember.A([yehuda, tom, seb])); + component.set('selection', tom); + }); + + this.render(); + + assert.deepEqual(component._selectize.items, ["2"]); + assert.equal(component._selectize.$dropdown_content.children().length, 3); + assert.equal(component._selectize.$dropdown_content.children().text(), 'Hi, Yehuda!Hi, Tom!Hi, Seb!'); + +}); \ No newline at end of file