diff --git a/packages/ember-htmlbars/lib/helpers/each.js b/packages/ember-htmlbars/lib/helpers/each.js
index 21966202180..08d5fee3fe8 100644
--- a/packages/ember-htmlbars/lib/helpers/each.js
+++ b/packages/ember-htmlbars/lib/helpers/each.js
@@ -1,4 +1,5 @@
import Ember from 'ember-metal/core';
+import Error from 'ember-metal/error';
import normalizeSelf from 'ember-htmlbars/utils/normalize-self';
import shouldDisplay from 'ember-views/streams/should_display';
import decodeEachKey from 'ember-htmlbars/utils/decode-each-key';
@@ -79,6 +80,7 @@ export default function eachHelper(params, hash, blocks) {
}
if (shouldDisplay(list)) {
+ let seenKeys = {};
forEach(list, (item, i) => {
var self;
if (blocks.template.arity === 0) {
@@ -86,6 +88,11 @@ export default function eachHelper(params, hash, blocks) {
}
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], self);
});
} 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 0466a04d66e..3496b077a03 100644
--- a/packages/ember-htmlbars/tests/helpers/each_test.js
+++ b/packages/ember-htmlbars/tests/helpers/each_test.js
@@ -1302,5 +1302,39 @@ 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() {
+ 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}}'.`
+ );
+});
+
+QUnit.test('pushing a new duplicate key will trigger a useful error (temporary until we can deal with this properly in HTMLBars)', function() {
+ runDestroy(view);
+ view = EmberView.create({
+ items: A(['a', 'b', 'c']),
+ template: compile('{{#each view.items as |item|}}{{item}}{{/each}}')
+ });
+
+ 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}}'.`
+ );
+});
+
testEachWithItem('{{#each foo in bar}}', false);
testEachWithItem('{{#each bar as |foo|}}', true);