diff --git a/packages/ember-htmlbars/lib/morphs/morph.js b/packages/ember-htmlbars/lib/morphs/morph.js
index a9739ab37c0..0b8f18a8c86 100644
--- a/packages/ember-htmlbars/lib/morphs/morph.js
+++ b/packages/ember-htmlbars/lib/morphs/morph.js
@@ -7,9 +7,16 @@ function EmberMorph(DOMHelper, contextualElement) {
this.HTMLBarsMorph$constructor(DOMHelper, contextualElement);
this.emberView = null;
- this.emberComponent = null;
this.emberToDestroy = null;
this.streamUnsubscribers = null;
+
+ // A component can become dirty either because one of its
+ // attributes changed, or because it was re-rendered. If any part
+ // of the component's template changes through observation, it has
+ // re-rendered from the perpsective of the programming model. This
+ // flag is set to true whenever a component becomes dirty because
+ // one of its attributes changed, which also triggers the attribute
+ // update flag (didUpdateAttrs).
this.shouldReceiveAttrs = false;
}
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 8ff5a403a4d..d57d6430095 100644
--- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
+++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
@@ -1,12 +1,11 @@
-import merge from "ember-metal/merge";
import Ember from "ember-metal/core";
+import { assign } from "ember-metal/merge";
import buildComponentTemplate from "ember-views/system/build-component-template";
import lookupComponent from "ember-htmlbars/utils/lookup-component";
import getCellOrValue from "ember-htmlbars/hooks/get-cell-or-value";
import { get } from "ember-metal/property_get";
import { set } from "ember-metal/property_set";
import setProperties from "ember-metal/set_properties";
-import View from "ember-views/views/view";
import { MUTABLE_CELL } from "ember-views/compat/attrs-proxy";
import { instrument } from "ember-htmlbars/system/instrumentation-support";
@@ -45,63 +44,31 @@ ComponentNodeManager.create = function(renderNode, env, options) {
return component || layout;
});
- //var componentInfo = { layout: found.layout };
-
if (component) {
let createOptions = { parentView };
- // Some attrs are special and need to be set as properties on the component
- // instance. Make sure we use getValue() to get them from `attrs` since
- // they are still streams.
- if (attrs.id) { createOptions.elementId = getValue(attrs.id); }
- if (attrs.tagName) { createOptions.tagName = getValue(attrs.tagName); }
- if (attrs._defaultTagName) { createOptions._defaultTagName = getValue(attrs._defaultTagName); }
- if (attrs.viewName) { createOptions.viewName = getValue(attrs.viewName); }
-
- if (component.create && parentScope && parentScope.self) {
- createOptions._context = getValue(parentScope.self);
- }
+ // Map passed attributes (e.g. ) to component
+ // properties ({ id: "foo" }).
+ configureCreateOptions(attrs, createOptions);
+ // If there is a controller on the scope, pluck it off and save it on the
+ // component. This allows the component to target actions sent via
+ // `sendAction` correctly.
if (parentScope.locals.controller) {
createOptions._controller = getValue(parentScope.locals.controller);
}
- component = createOrUpdateComponent(component, createOptions, renderNode, env, attrs);
-
- // Even though we looked up a layout from the container earlier, the
- // component may specify a `layout` property that overrides that.
- // The component may also provide a `template` property we should
- // respect (though this behavior is deprecated).
- let componentLayout = get(component, 'layout');
- let componentTemplate = get(component, 'template');
-
- if (componentLayout) {
- layout = componentLayout;
+ // Instantiate the component
+ component = createComponent(component, createOptions, renderNode, env, attrs);
- // There is no block template provided but the component has a
- // `template` property.
- if ((!templates || !templates.default) && componentTemplate) {
- Ember.deprecate("Using deprecated `template` property on a Component.");
- templates = { default: componentTemplate.raw };
- }
- } else if (componentTemplate) {
- // If the component has a `template` but no `layout`, use the template
- // as the layout.
- layout = componentTemplate;
- }
-
- renderNode.emberView = component;
+ // If the component specifies its template via the `layout` or `template`
+ // properties instead of using the template looked up in the container, get
+ // them now that we have the component instance.
+ let result = extractComponentTemplates(component, templates);
+ layout = result.layout || layout;
+ templates = result.templates || templates;
- if (component.positionalParams) {
- // 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