diff --git a/packages/ember-htmlbars/lib/utils/extract-positional-params.js b/packages/ember-htmlbars/lib/utils/extract-positional-params.js index 06d3698a7fe..75669f1f250 100644 --- a/packages/ember-htmlbars/lib/utils/extract-positional-params.js +++ b/packages/ember-htmlbars/lib/utils/extract-positional-params.js @@ -34,9 +34,16 @@ function processNamedPositionalParameters(renderNode, positionalParams, params, } function processRestPositionalParameters(renderNode, positionalParamsName, params, attrs) { + let nameInAttrs = positionalParamsName in attrs; + + // when no params are used, do not override the specified `attrs.stringParamName` value + if (params.length === 0 && nameInAttrs) { + return; + } + // If there is already an attribute for that variable, do nothing assert(`You cannot specify positional parameters and the hash argument \`${positionalParamsName}\`.`, - !(positionalParamsName in attrs)); + !nameInAttrs); let paramsStream = new Stream(() => { return readArray(params.slice(0)); diff --git a/packages/ember-htmlbars/tests/integration/component_invocation_test.js b/packages/ember-htmlbars/tests/integration/component_invocation_test.js index ea4b324cc07..b7ac84d93b1 100644 --- a/packages/ember-htmlbars/tests/integration/component_invocation_test.js +++ b/packages/ember-htmlbars/tests/integration/component_invocation_test.js @@ -453,6 +453,57 @@ QUnit.test('arbitrary positional parameter conflict with hash parameter is repor }, `You cannot specify positional parameters and the hash argument \`names\`.`); }); +QUnit.test('can use hash parameter instead of arbitrary positional param [GH #12444]', function() { + var SampleComponent = Component.extend(); + SampleComponent.reopenClass({ + positionalParams: 'names' + }); + + registry.register('template:components/sample-component', compile('{{#each attrs.names as |name|}}{{name}}{{/each}}')); + registry.register('component:sample-component', SampleComponent); + + view = EmberView.extend({ + layout: compile('{{sample-component names=things id="args-3"}}'), + container: container, + context: { + things: ['Foo', 4, 'Bar'] + } + }).create(); + + runAppend(view); + + equal(view.$('#args-3').text(), 'Foo4Bar'); +}); + +QUnit.test('can use hash parameter instead of positional param', function() { + var SampleComponent = Component.extend(); + SampleComponent.reopenClass({ + positionalParams: ['first', 'second'] + }); + + registry.register('template:components/sample-component', compile('{{attrs.first}} - {{attrs.second}}')); + registry.register('component:sample-component', SampleComponent); + + view = EmberView.extend({ + layout: compile(` + {{sample-component "one" "two" id="two-positional"}} + {{sample-component "one" second="two" id="one-positional"}} + {{sample-component first="one" second="two" id="no-positional"}} + + `), + container: container, + context: { + things: ['Foo', 4, 'Bar'] + } + }).create(); + + runAppend(view); + + equal(view.$('#two-positional').text(), 'one - two'); + equal(view.$('#one-positional').text(), 'one - two'); + equal(view.$('#no-positional').text(), 'one - two'); +}); + QUnit.test('dynamic arbitrary number of positional parameters', function() { var SampleComponent = Component.extend(); SampleComponent.reopenClass({