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