diff --git a/package.json b/package.json index 7fc110ccc01..b1d423b05c9 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "finalhandler": "^0.4.0", "github": "^0.2.3", "glob": "~4.3.2", - "htmlbars": "0.13.33", + "htmlbars": "0.13.34", "qunit-extras": "^1.3.0", "qunitjs": "^1.16.0", "route-recognizer": "0.1.5", diff --git a/packages/ember-htmlbars/lib/helpers/each.js b/packages/ember-htmlbars/lib/helpers/each.js index 8f64ab9ce47..25bcc3cdbeb 100644 --- a/packages/ember-htmlbars/lib/helpers/each.js +++ b/packages/ember-htmlbars/lib/helpers/each.js @@ -1,4 +1,3 @@ -import Error from 'ember-metal/error'; import shouldDisplay from 'ember-views/streams/should_display'; import decodeEachKey from 'ember-htmlbars/utils/decode-each-key'; @@ -74,14 +73,9 @@ export default function eachHelper(params, hash, blocks) { var keyPath = hash.key; if (shouldDisplay(list)) { - let seenKeys = {}; forEach(list, (item, i) => { var key = decodeEachKey(item, keyPath, i); - if (seenKeys[key] === true) { - throw new Error(`Duplicate key found ('${key}') for '{{each}}' helper, please use a unique key or switch to '{{#each model key="@index"}}{{/each}}'.`); - } else { - seenKeys[key] = true; - } + blocks.template.yieldItem(key, [item, i]); }); } else if (blocks.inverse.yield) { diff --git a/packages/ember-htmlbars/tests/helpers/each_test.js b/packages/ember-htmlbars/tests/helpers/each_test.js index d51e84c3227..d00449f7e07 100644 --- a/packages/ember-htmlbars/tests/helpers/each_test.js +++ b/packages/ember-htmlbars/tests/helpers/each_test.js @@ -759,22 +759,19 @@ QUnit.test('can specify `@identity` to represent mixed object and primitive item equal(view.$().text(), 'foobarbaz'); }); -QUnit.test('duplicate keys trigger a useful error (temporary until we can deal with this properly in HTMLBars)', function() { +QUnit.test('duplicate keys work properly with primitive items', function() { runDestroy(view); view = EmberView.create({ items: ['a', 'a', 'a'], template: compile('{{#each view.items as |item|}}{{item}}{{/each}}') }); - throws( - function() { - runAppend(view); - }, - `Duplicate key found ('a') for '{{each}}' helper, please use a unique key or switch to '{{#each model key="@index"}}{{/each}}'.` - ); + runAppend(view); + + equal(view.$().text(), 'aaa'); }); -QUnit.test('pushing a new duplicate key will trigger a useful error (temporary until we can deal with this properly in HTMLBars)', function() { +QUnit.test('pushing a new duplicate key will render properly with primitive items', function() { runDestroy(view); view = EmberView.create({ items: A(['a', 'b', 'c']), @@ -783,12 +780,49 @@ QUnit.test('pushing a new duplicate key will trigger a useful error (temporary u runAppend(view); - throws( - function() { - run(function() { - view.get('items').pushObject('a'); - }); - }, - `Duplicate key found ('a') for '{{each}}' helper, please use a unique key or switch to '{{#each model key="@index"}}{{/each}}'.` - ); + run(function() { + view.get('items').pushObject('a'); + }); + + equal(view.$().text(), 'abca'); +}); + +QUnit.test('duplicate keys work properly with objects', function() { + runDestroy(view); + let duplicateItem = { display: 'foo' }; + view = EmberView.create({ + items: [ + duplicateItem, + duplicateItem, + { display: 'bar' }, + { display: 'qux' } + ], + template: compile('{{#each view.items as |item|}}{{item.display}}{{/each}}') + }); + + runAppend(view); + + equal(view.$().text(), 'foofoobarqux'); +}); + +QUnit.test('pushing a new duplicate key will render properly with objects', function() { + runDestroy(view); + + let duplicateItem = { display: 'foo' }; + view = EmberView.create({ + items: A([ + duplicateItem, + { display: 'bar' }, + { display: 'qux' } + ]), + template: compile('{{#each view.items as |item|}}{{item.display}}{{/each}}') + }); + + runAppend(view); + + run(function() { + view.get('items').pushObject(duplicateItem); + }); + + equal(view.$().text(), 'foobarquxfoo'); });