diff --git a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
index 222d329823d..315ec8d1bf6 100644
--- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
+++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
@@ -10,6 +10,8 @@ import { MUTABLE_CELL } from "ember-views/compat/attrs-proxy";
import SafeString from "htmlbars-util/safe-string";
import { instrument } from "ember-htmlbars/system/instrumentation-support";
import EmberComponent from "ember-views/views/component";
+import Stream from 'ember-metal/streams/stream';
+import { readArray } from 'ember-metal/streams/utils';
// In theory this should come through the env, but it should
// be safe to import this until we make the hook system public
@@ -89,10 +91,26 @@ function extractPositionalParams(renderNode, component, params, attrs) {
// if the component is rendered via {{component}} helper, the first
// element of `params` is the name of the component, so we need to
// skip that when the positional parameters are constructed
- let paramsStartIndex = renderNode.state.isComponentHelper ? 1 : 0;
- let pp = component.positionalParams;
- for (let i=0; i {
+ return readArray(params.slice(paramsStartIndex));
+ }, 'params');
+
+ attrs[positionalParams] = paramsStream;
+ }
+
+ for (let i=0; i < positionalParams.length; i++) {
+ let param = params[paramsStartIndex + i];
+ if (isNamed) {
+ paramsStream.addDependency(param);
+ } else {
+ attrs[positionalParams[i]] = param;
+ }
}
}
}
diff --git a/packages/ember-htmlbars/tests/integration/component_invocation_test.js b/packages/ember-htmlbars/tests/integration/component_invocation_test.js
index 665a3ef3f56..7165f50f330 100644
--- a/packages/ember-htmlbars/tests/integration/component_invocation_test.js
+++ b/packages/ember-htmlbars/tests/integration/component_invocation_test.js
@@ -6,6 +6,7 @@ import ComponentLookup from 'ember-views/component_lookup';
import Component from "ember-views/views/component";
import { runAppend, runDestroy } from "ember-runtime/tests/utils";
import { get } from "ember-metal/property_get";
+import { set } from "ember-metal/property_set";
import run from "ember-metal/run_loop";
var registry, container, view;
@@ -258,7 +259,7 @@ if (Ember.FEATURES.isEnabled('ember-views-component-block-info')) {
});
}
-QUnit.test('static positional parameters', function() {
+QUnit.test('static named positional parameters', function() {
registry.register('template:components/sample-component', compile('{{attrs.name}}{{attrs.age}}'));
registry.register('component:sample-component', Component.extend({
positionalParams: ['name', 'age']
@@ -274,7 +275,7 @@ QUnit.test('static positional parameters', function() {
equal(jQuery('#qunit-fixture').text(), 'Quint4');
});
-QUnit.test('dynamic positional parameters', function() {
+QUnit.test('dynamic named positional parameters', function() {
registry.register('template:components/sample-component', compile('{{attrs.name}}{{attrs.age}}'));
registry.register('component:sample-component', Component.extend({
positionalParams: ['name', 'age']
@@ -292,13 +293,58 @@ QUnit.test('dynamic positional parameters', function() {
runAppend(view);
equal(jQuery('#qunit-fixture').text(), 'Quint4');
run(function() {
- Ember.set(view.context, 'myName', 'Edward');
- Ember.set(view.context, 'myAge', '5');
+ set(view.context, 'myName', 'Edward');
+ set(view.context, 'myAge', '5');
});
equal(jQuery('#qunit-fixture').text(), 'Edward5');
});
+QUnit.test('static arbitrary number of positional parameters', function() {
+ registry.register('template:components/sample-component', compile('{{#each attrs.names as |name|}}{{name}}{{/each}}'));
+ registry.register('component:sample-component', Component.extend({
+ positionalParams: 'names'
+ }));
+
+ view = EmberView.extend({
+ layout: compile('{{sample-component "Foo" 4 "Bar" id="args-3"}}{{sample-component "Foo" 4 "Bar" 5 "Baz" id="args-5"}}{{component "sample-component" "Foo" 4 "Bar" 5 "Baz" id="helper"}}'),
+ container: container
+ }).create();
+
+ runAppend(view);
+
+ equal(view.$('#args-3').text(), 'Foo4Bar');
+ equal(view.$('#args-5').text(), 'Foo4Bar5Baz');
+ equal(view.$('#helper').text(), 'Foo4Bar5Baz');
+});
+
+QUnit.test('dynamic arbitrary number of positional parameters', function() {
+ registry.register('template:components/sample-component', compile('{{#each attrs.names as |name|}}{{name}}{{/each}}'));
+ registry.register('component:sample-component', Component.extend({
+ positionalParams: 'names'
+ }));
+
+ view = EmberView.extend({
+ layout: compile('{{sample-component user1 user2 id="direct"}}{{component "sample-component" user1 user2 id="helper"}}'),
+ container: container,
+ context: {
+ user1: 'Foo',
+ user2: 4
+ }
+ }).create();
+
+ runAppend(view);
+ equal(view.$('#direct').text(), 'Foo4');
+ equal(view.$('#helper').text(), 'Foo4');
+ run(function() {
+ set(view.context, 'user1', 'Bar');
+ set(view.context, 'user2', '5');
+ });
+
+ equal(view.$('#direct').text(), 'Bar5');
+ equal(view.$('#helper').text(), 'Bar5');
+});
+
QUnit.test('moduleName is available on _renderNode when a layout is present', function() {
expect(1);
@@ -360,8 +406,8 @@ if (Ember.FEATURES.isEnabled('ember-htmlbars-component-helper')) {
runAppend(view);
equal(jQuery('#qunit-fixture').text(), 'Quint4');
run(function() {
- Ember.set(view.context, 'myName', 'Edward');
- Ember.set(view.context, 'myAge', '5');
+ set(view.context, 'myName', 'Edward');
+ set(view.context, 'myAge', '5');
});
equal(jQuery('#qunit-fixture').text(), 'Edward5');
@@ -382,7 +428,7 @@ QUnit.test('yield to inverse', function() {
runAppend(view);
equal(jQuery('#qunit-fixture').text(), 'Yes:Hello42');
run(function() {
- Ember.set(view.context, 'activated', false);
+ set(view.context, 'activated', false);
});
equal(jQuery('#qunit-fixture').text(), 'No:Goodbye');