diff --git a/packages/ember-htmlbars/lib/system/merge-view-bindings.js b/packages/ember-htmlbars/lib/system/merge-view-bindings.js index d6be898e53c..912f4af1070 100644 --- a/packages/ember-htmlbars/lib/system/merge-view-bindings.js +++ b/packages/ember-htmlbars/lib/system/merge-view-bindings.js @@ -29,6 +29,12 @@ function mergeGenericViewBindings(view, props, hash) { if (IS_BINDING.test(key)) { if (typeof value === 'string') { + Ember.deprecate( + "You're attempting to render a view by passing " + key + " " + + "to a view helper, but this syntax is deprecated. You should use `" + + key.slice(0, -7) + "=someValue` instead." + ); + props[key] = view._getBindingForStream(value); } else if (isStream(value)) { Ember.deprecate( diff --git a/packages/ember-htmlbars/tests/helpers/collection_test.js b/packages/ember-htmlbars/tests/helpers/collection_test.js index 1fb5b166502..1df47c5f0d3 100644 --- a/packages/ember-htmlbars/tests/helpers/collection_test.js +++ b/packages/ember-htmlbars/tests/helpers/collection_test.js @@ -356,7 +356,7 @@ QUnit.test("should give its item views the class specified by itemClass", functi equal(view.$('ul li.baz').length, 3, "adds class attribute"); }); -QUnit.test("should give its item views the classBinding specified by itemClassBinding", function() { +QUnit.test("should give its item views the class specified by itemClass", function() { var ItemClassBindingTestCollectionView = CollectionView.extend({ tagName: 'ul', content: A([EmberObject.create({ isBaz: false }), EmberObject.create({ isBaz: true }), EmberObject.create({ isBaz: true })]) @@ -365,7 +365,7 @@ QUnit.test("should give its item views the classBinding specified by itemClassBi view = EmberView.create({ itemClassBindingTestCollectionView: ItemClassBindingTestCollectionView, isBar: true, - template: compile('{{#collection view.itemClassBindingTestCollectionView itemClassBinding="view.isBar"}}foo{{/collection}}') + template: compile('{{#collection view.itemClassBindingTestCollectionView itemClass=view.isBar}}foo{{/collection}}') }); runAppend(view); @@ -376,7 +376,7 @@ QUnit.test("should give its item views the classBinding specified by itemClassBi // to introduce a new keyword that could be used from within `itemClassBinding`. For instance, `itemClassBinding="item.isBaz"`. }); -QUnit.test("should give its item views the property specified by itemPropertyBinding", function() { +QUnit.test("should give its item views the property specified by itemProperty", function() { var ItemPropertyBindingTestItemView = EmberView.extend({ tagName: 'li' }); @@ -391,7 +391,7 @@ QUnit.test("should give its item views the property specified by itemPropertyBin return ItemPropertyBindingTestItemView; } }, - template: compile('{{#collection contentBinding="view.content" tagName="ul" itemViewClass="item-property-binding-test-item-view" itemProperty=view.baz preserveContext=false}}{{view.property}}{{/collection}}') + template: compile('{{#collection content=view.content tagName="ul" itemViewClass="item-property-binding-test-item-view" itemProperty=view.baz preserveContext=false}}{{view.property}}{{/collection}}') }); runAppend(view); @@ -413,7 +413,7 @@ QUnit.test("should unsubscribe stream bindings", function() { view = EmberView.create({ baz: "baz", content: A([EmberObject.create(), EmberObject.create(), EmberObject.create()]), - template: compile('{{#collection contentBinding="view.content" itemProperty=view.baz}}{{view.property}}{{/collection}}') + template: compile('{{#collection content=view.content itemProperty=view.baz}}{{view.property}}{{/collection}}') }); runAppend(view); @@ -686,7 +686,7 @@ QUnit.test("context should be content", function() { controller: { items: items }, - template: compile('{{collection contentBinding="items" itemViewClass="an-item"}}') + template: compile('{{collection content=items itemViewClass="an-item"}}') }); runAppend(view); diff --git a/packages/ember-htmlbars/tests/helpers/each_test.js b/packages/ember-htmlbars/tests/helpers/each_test.js index f3a813a6a58..dec027abd36 100644 --- a/packages/ember-htmlbars/tests/helpers/each_test.js +++ b/packages/ember-htmlbars/tests/helpers/each_test.js @@ -903,7 +903,7 @@ function testEachWithItem(moduleName, useBlockParams) { view = EmberView.create({ container: container, controller: controller, - template: templateFor('{{#EACH|this|personController}}{{#view controllerBinding="personController"}}{{name}}{{/view}}{{/each}}', useBlockParams) + template: templateFor('{{#EACH|this|personController}}{{#view controller=personController}}{{name}}{{/view}}{{/each}}', useBlockParams) }); runAppend(view); diff --git a/packages/ember-htmlbars/tests/helpers/view_test.js b/packages/ember-htmlbars/tests/helpers/view_test.js index c0fe662728e..7ac5035cd02 100644 --- a/packages/ember-htmlbars/tests/helpers/view_test.js +++ b/packages/ember-htmlbars/tests/helpers/view_test.js @@ -279,8 +279,8 @@ QUnit.test("mixing old and new styles of property binding fires a warning, treat Ember.warn = oldWarn; }); -QUnit.test('"Binding"-suffixed bindings are runloop-synchronized', function() { - expect(5); +QUnit.test('"Binding"-suffixed bindings are runloop-synchronized [DEPRECATED]', function() { + expect(6); var subview; @@ -299,7 +299,10 @@ QUnit.test('"Binding"-suffixed bindings are runloop-synchronized', function() { }); view = View.create(); - runAppend(view); + + expectDeprecation(function() { + runAppend(view); + }, /You're attempting to render a view by passing colorBinding to a view helper, but this syntax is deprecated. You should use `color=someValue` instead./); equal(view.$('h1 .color').text(), 'mauve', 'renders bound value'); @@ -992,7 +995,7 @@ QUnit.test('{{view}} should evaluate other attributes bindings set in the curren view = EmberView.create({ name: 'myView', textField: TextField, - template: compile('{{view view.textField valueBinding="view.name"}}') + template: compile('{{view view.textField value=view.name}}') }); runAppend(view); @@ -1064,7 +1067,7 @@ QUnit.test('a view helper\'s bindings are to the parent context', function() { name: 'foo' }), Subview: Subview, - template: compile('

{{view view.Subview colorBinding="color" someControllerBinding="this"}}

') + template: compile('

{{view view.Subview color=color someController=this}}

') }); view = View.create(); @@ -1179,7 +1182,7 @@ QUnit.test('should work with precompiled templates', function() { equal(view.$().text(), 'updated', 'the precompiled template was updated'); }); -QUnit.test('bindings should be relative to the current context', function() { +QUnit.test('bindings should be relative to the current context [DEPRECATED]', function() { view = EmberView.create({ museumOpen: true, @@ -1195,12 +1198,14 @@ QUnit.test('bindings should be relative to the current context', function() { template: compile('{{#if view.museumOpen}} {{view view.museumView nameBinding="view.museumDetails.name" dollarsBinding="view.museumDetails.price"}} {{/if}}') }); - runAppend(view); + expectDeprecation(function() { + runAppend(view); + }, /You're attempting to render a view by passing .+Binding to a view helper, but this syntax is deprecated/); equal(trim(view.$().text()), 'Name: SFMoMA Price: $20', 'should print baz twice'); }); -QUnit.test('bindings should respect keywords', function() { +QUnit.test('bindings should respect keywords [DEPRECATED]', function() { view = EmberView.create({ museumOpen: true, @@ -1219,6 +1224,32 @@ QUnit.test('bindings should respect keywords', function() { template: compile('{{#if view.museumOpen}}{{view view.museumView nameBinding="controller.museumDetails.name" dollarsBinding="controller.museumDetails.price"}}{{/if}}') }); + expectDeprecation(function() { + runAppend(view); + }, /You're attempting to render a view by passing .+Binding to a view helper, but this syntax is deprecated/); + + equal(trim(view.$().text()), 'Name: SFMoMA Price: $20', 'should print baz twice'); +}); + +QUnit.test('should respect keywords', function() { + view = EmberView.create({ + museumOpen: true, + + controller: { + museumOpen: true, + museumDetails: EmberObject.create({ + name: 'SFMoMA', + price: 20 + }) + }, + + museumView: EmberView.extend({ + template: compile('Name: {{view.name}} Price: ${{view.dollars}}') + }), + + template: compile('{{#if view.museumOpen}}{{view view.museumView name=controller.museumDetails.name dollars=controller.museumDetails.price}}{{/if}}') + }); + runAppend(view); equal(trim(view.$().text()), 'Name: SFMoMA Price: $20', 'should print baz twice'); diff --git a/packages/ember-htmlbars/tests/helpers/yield_test.js b/packages/ember-htmlbars/tests/helpers/yield_test.js index 74ba5fcc968..08fe6236b37 100644 --- a/packages/ember-htmlbars/tests/helpers/yield_test.js +++ b/packages/ember-htmlbars/tests/helpers/yield_test.js @@ -201,7 +201,7 @@ QUnit.test("can bind a keyword to a component and use it in yield", function() { view = EmberView.create({ controller: { boundText: "outer", component: component }, - template: compile('{{#with boundText as item}}{{#view component contentBinding="item"}}{{item}}{{/view}}{{/with}}') + template: compile('{{#with boundText as item}}{{#view component content=item}}{{item}}{{/view}}{{/with}}') }); runAppend(view); diff --git a/packages/ember-htmlbars/tests/integration/select_in_template_test.js b/packages/ember-htmlbars/tests/integration/select_in_template_test.js index 08daa4fa230..af7bfc92673 100644 --- a/packages/ember-htmlbars/tests/integration/select_in_template_test.js +++ b/packages/ember-htmlbars/tests/integration/select_in_template_test.js @@ -25,7 +25,7 @@ QUnit.module("ember-htmlbars: Ember.Select - usage inside templates", { } }); -QUnit.test("works from a template with bindings", function() { +QUnit.test("works from a template with bindings [DEPRECATED]", function() { var Person = EmberObject.extend({ id: null, firstName: null, @@ -66,6 +66,70 @@ QUnit.test("works from a template with bindings", function() { ) }); + expectDeprecation(function() { + runAppend(view); + }, /You're attempting to render a view by passing .+Binding to a view helper, but this syntax is deprecated/); + + var select = view.get('select'); + ok(select.$().length, "Select was rendered"); + equal(select.$('option').length, 5, "Options were rendered"); + equal(select.$().text(), "Pick a person:Yehuda KatzTom DalePeter WagenetErik Bryn\n", "Option values were rendered"); + equal(select.get('selection'), null, "Nothing has been selected"); + + run(function() { + application.selectedPersonController.set('person', erik); + }); + + equal(select.get('selection'), erik, "Selection was updated through binding"); + run(function() { + application.peopleController.pushObject(Person.create({ id: 5, firstName: "James", lastName: "Rosen" })); + }); + + equal(select.$('option').length, 6, "New option was added"); + equal(select.get('selection'), erik, "Selection was maintained after new option was added"); +}); + +QUnit.test("works from a template", function() { + var Person = EmberObject.extend({ + id: null, + firstName: null, + lastName: null, + + fullName: computed(function() { + return this.get('firstName') + " " + this.get('lastName'); + }).property('firstName', 'lastName') + }); + + var erik = Person.create({ id: 4, firstName: 'Erik', lastName: 'Bryn' }); + + var application = Namespace.create(); + + application.peopleController = ArrayController.create({ + content: Ember.A([ + Person.create({ id: 1, firstName: 'Yehuda', lastName: 'Katz' }), + Person.create({ id: 2, firstName: 'Tom', lastName: 'Dale' }), + Person.create({ id: 3, firstName: 'Peter', lastName: 'Wagenet' }), + erik + ]) + }); + + application.selectedPersonController = EmberObject.create({ + person: null + }); + + view = EmberView.create({ + app: application, + selectView: SelectView, + template: compile( + '{{view view.selectView viewName="select"' + + ' content=view.app.peopleController' + + ' optionLabelPath="content.fullName"' + + ' optionValuePath="content.id"' + + ' prompt="Pick a person:"' + + ' selection=view.app.selectedPersonController.person}}' + ) + }); + runAppend(view); var select = view.get('select'); @@ -96,8 +160,8 @@ QUnit.test("upon content change, the DOM should reflect the selection (#481)", f selectView: SelectView, template: compile( '{{view view.selectView viewName="select"' + - ' contentBinding="view.user.options"' + - ' selectionBinding="view.user.selectedOption"}}' + ' content=view.user.options' + + ' selection=view.user.selectedOption}}' ) }); @@ -131,8 +195,8 @@ QUnit.test("upon content change with Array-like content, the DOM should reflect selectView: SelectView, template: compile( '{{view view.selectView viewName="select"' + - ' contentBinding="view.proxy"' + - ' selectionBinding="view.proxy.selectedOption"}}' + ' content=view.proxy' + + ' selection=view.proxy.selectedOption}}' ) }); @@ -177,7 +241,9 @@ function testValueBinding(templateString) { equal(selectEl.selectedIndex, 1, "The DOM is updated to reflect the new selection"); } -QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using valueBinding (old xBinding='' syntax)", function() { +QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using valueBinding [DEPRECATED]", function() { + expectDeprecation(/You're attempting to render a view by passing .+Binding to a view helper, but this syntax is deprecated./); + testValueBinding( '{{view view.selectView viewName="select"' + ' contentBinding="view.collection"' + @@ -188,7 +254,7 @@ QUnit.test("select element should correctly initialize and update selectedIndex ); }); -QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using valueBinding (new quoteless binding shorthand)", function() { +QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using a bound value", function() { testValueBinding( '{{view view.selectView viewName="select"' + ' content=view.collection' + @@ -227,7 +293,9 @@ function testSelectionBinding(templateString) { equal(select.$('option:eq(1)').prop('selected'), true, "Selected property is set to proper option"); } -QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using selectionBinding (old xBinding='' syntax)", function() { +QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using selectionBinding [DEPRECATED]", function() { + expectDeprecation(/You're attempting to render a view by passing .+Binding to a view helper, but this syntax is deprecated./); + testSelectionBinding( '{{view view.selectView viewName="select"' + ' contentBinding="view.collection"' + @@ -238,7 +306,7 @@ QUnit.test("select element should correctly initialize and update selectedIndex ); }); -QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using selectionBinding (new quoteless binding shorthand)", function() { +QUnit.test("select element should correctly initialize and update selectedIndex and bound properties when using a bound selection", function() { testSelectionBinding( '{{view view.selectView viewName="select"' + ' content=view.collection' +