From 6e3085ab0c4db92014c2d5089c1db205b8e051a9 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 22 Jul 2015 07:33:46 -0400 Subject: [PATCH 1/2] [BUGFIX release] Update HTMLBars to allow duplicate {{each}} keys. --- package.json | 2 +- packages/ember-htmlbars/lib/helpers/each.js | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) 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) { From 3204d4eea4494b448bb3780073c191197c92f9c9 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 22 Jul 2015 07:39:44 -0400 Subject: [PATCH 2/2] [BUGFIX release] Test {{each}} with duplicate items. --- .../ember-htmlbars/tests/helpers/each_test.js | 66 ++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) 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'); });