diff --git a/packages/ember-htmlbars/lib/hooks/component.js b/packages/ember-htmlbars/lib/hooks/component.js
index 927052f1656..fe589b35b5f 100644
--- a/packages/ember-htmlbars/lib/hooks/component.js
+++ b/packages/ember-htmlbars/lib/hooks/component.js
@@ -12,6 +12,7 @@ import {
COMPONENT_HASH,
isComponentCell,
mergeInNewHash,
+ processPositionalParamsFromCell,
} from 'ember-htmlbars/keywords/closure-component';
var IS_ANGLE_CACHE = new Cache(1000, function(key) {
@@ -33,6 +34,21 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
let componentCell = stream.value();
if (isComponentCell(componentCell)) {
tagName = componentCell[COMPONENT_PATH];
+
+ /*
+ * Processing positional params before merging into a hash must be done
+ * here to avoid problems with rest positional parameters rendered using
+ * the dot notation.
+ *
+ * Closure components (for the contextual component feature) do not
+ * actually keep the positional params, but process them at each level.
+ * Therefore, when rendering a closure component with the component
+ * helper we process the parameters and attributes and then merge those
+ * on top of the closure component attributes.
+ *
+ */
+ processPositionalParamsFromCell(componentCell, params, attrs);
+ params = [];
attrs = mergeInNewHash(componentCell[COMPONENT_HASH], attrs);
}
}
diff --git a/packages/ember-htmlbars/lib/keywords/closure-component.js b/packages/ember-htmlbars/lib/keywords/closure-component.js
index 79a76687f1f..3c53d273435 100644
--- a/packages/ember-htmlbars/lib/keywords/closure-component.js
+++ b/packages/ember-htmlbars/lib/keywords/closure-component.js
@@ -74,19 +74,23 @@ export function isComponentCell(component) {
}
function createNestedClosureComponentCell(componentCell, params, hash) {
- let positionalParams = componentCell[COMPONENT_POSITIONAL_PARAMS];
-
// This needs to be done in each nesting level to avoid raising assertions
- processPositionalParams(null, positionalParams, params, hash);
+ processPositionalParamsFromCell(componentCell, params, hash);
return {
[COMPONENT_PATH]: componentCell[COMPONENT_PATH],
[COMPONENT_HASH]: mergeInNewHash(componentCell[COMPONENT_HASH], hash),
- [COMPONENT_POSITIONAL_PARAMS]: positionalParams,
+ [COMPONENT_POSITIONAL_PARAMS]: componentCell[COMPONENT_POSITIONAL_PARAMS],
[COMPONENT_CELL]: true
};
}
+export function processPositionalParamsFromCell(componentCell, params, hash) {
+ let positionalParams = componentCell[COMPONENT_POSITIONAL_PARAMS];
+
+ processPositionalParams(null, positionalParams, params, hash);
+}
+
function createNewClosureComponentCell(env, componentPath, params, hash) {
let positionalParams = getPositionalParams(env.owner, componentPath);
diff --git a/packages/ember-htmlbars/lib/keywords/element-component.js b/packages/ember-htmlbars/lib/keywords/element-component.js
index 8878e4c61b6..84b9556cec6 100644
--- a/packages/ember-htmlbars/lib/keywords/element-component.js
+++ b/packages/ember-htmlbars/lib/keywords/element-component.js
@@ -1,12 +1,11 @@
import assign from 'ember-metal/assign';
import {
COMPONENT_PATH,
- COMPONENT_POSITIONAL_PARAMS,
COMPONENT_HASH,
isComponentCell,
mergeInNewHash,
+ processPositionalParamsFromCell,
} from './closure-component';
-import { processPositionalParams } from 'ember-htmlbars/utils/extract-positional-params';
export default {
setupState(lastState, env, scope, params, hash) {
@@ -58,10 +57,9 @@ function render(morph, env, scope, [path, ...params], hash, template, inverse, v
if (isComponentCell(path)) {
let closureComponent = env.hooks.getValue(path);
- let positionalParams = closureComponent[COMPONENT_POSITIONAL_PARAMS];
// This needs to be done in each nesting level to avoid raising assertions
- processPositionalParams(null, positionalParams, params, hash);
+ processPositionalParamsFromCell(closureComponent, params, hash);
params = [];
hash = mergeInNewHash(closureComponent[COMPONENT_HASH], hash);
}
diff --git a/packages/ember-htmlbars/lib/utils/extract-positional-params.js b/packages/ember-htmlbars/lib/utils/extract-positional-params.js
index bc412c6adb4..8747920396b 100644
--- a/packages/ember-htmlbars/lib/utils/extract-positional-params.js
+++ b/packages/ember-htmlbars/lib/utils/extract-positional-params.js
@@ -11,9 +11,9 @@ export default function extractPositionalParams(renderNode, component, params, a
}
export function processPositionalParams(renderNode, positionalParams, params, attrs) {
- let isNamed = typeof positionalParams === 'string';
+ let isRest = typeof positionalParams === 'string';
- if (isNamed) {
+ if (isRest) {
processRestPositionalParameters(renderNode, positionalParams, params, attrs);
} else {
processNamedPositionalParameters(renderNode, positionalParams, params, attrs);
diff --git a/packages/ember-htmlbars/tests/helpers/closure_component_test.js b/packages/ember-htmlbars/tests/helpers/closure_component_test.js
index 5b3c37ef7e9..dde15a187f1 100644
--- a/packages/ember-htmlbars/tests/helpers/closure_component_test.js
+++ b/packages/ember-htmlbars/tests/helpers/closure_component_test.js
@@ -429,6 +429,33 @@ if (isEnabled('ember-contextual-components')) {
equal(component.$().text(), expectedText, '-looked-up component rendered');
});
+ QUnit.test('renders with dot path and with rest positional parameters', function() {
+ let LookedUp = Component.extend();
+ LookedUp.reopenClass({
+ positionalParams: 'params'
+ });
+ owner.register(
+ 'component:-looked-up',
+ LookedUp
+ );
+ let expectedText = 'Hodi';
+ owner.register(
+ 'template:components/-looked-up',
+ compile('{{params}}')
+ );
+
+ let template = compile('{{#with (hash lookedup=(component "-looked-up")) as |object|}}{{object.lookedup expectedText "Hola"}}{{/with}}');
+ component = Component.extend({
+ [OWNER]: owner,
+ template
+ }).create({
+ expectedText
+ });
+
+ runAppend(component);
+ equal(component.$().text(), `${expectedText},Hola`, '-looked-up component rendered with rest params');
+ });
+
QUnit.test('adding parameters to a closure component\'s instance does not add it to other instances', function(assert) {
owner.register(
'template:components/select-box',