diff --git a/packages/ember-glimmer/lib/component.js b/packages/ember-glimmer/lib/component.js index 56676be7ec5..d2687b90b4b 100644 --- a/packages/ember-glimmer/lib/component.js +++ b/packages/ember-glimmer/lib/component.js @@ -5,7 +5,8 @@ import { ChildViewsSupport, ViewStateSupport, ViewMixin, - ActionSupport + ActionSupport, + getViewElement } from 'ember-views'; import { TargetActionSupport } from 'ember-runtime'; import { @@ -227,7 +228,8 @@ const Component = CoreView.extend( @public */ readDOMAttr(name) { - return readDOMAttr(this.element, name); + let element = getViewElement(this); + return readDOMAttr(element, name); } /** diff --git a/packages/ember-glimmer/lib/renderer.js b/packages/ember-glimmer/lib/renderer.js index bb2e01a0800..691e08a4893 100644 --- a/packages/ember-glimmer/lib/renderer.js +++ b/packages/ember-glimmer/lib/renderer.js @@ -9,6 +9,8 @@ import { import { CURRENT_TAG, UNDEFINED_REFERENCE } from 'glimmer-reference'; import { fallbackViewRegistry, + getViewElement, + setViewElement, getViewId } from 'ember-views'; import { BOUNDS } from './component'; @@ -163,7 +165,7 @@ function loopEnd(current, next) { backburner.on('begin', loopBegin); backburner.on('end', loopEnd); -export class Renderer { +class Renderer { constructor(env, rootTemplate, _viewRegistry = fallbackViewRegistry, destinedForDOM = false) { this._env = env; this._rootTemplate = rootTemplate; @@ -226,9 +228,9 @@ export class Renderer { remove(view) { view._transitionTo('destroying'); - view.element = null; + setViewElement(view, null); - if (this._env.isInteractive) { + if (this._destinedForDOM) { view.trigger('didDestroyElement'); } @@ -265,6 +267,10 @@ export class Renderer { this._clearAllRoots(); } + getElement(view) { + // overriden in the subclasses + } + getBounds(view) { let bounds = view[BOUNDS]; @@ -400,14 +406,22 @@ export class Renderer { } } -export const InertRenderer = { - create({ env, rootTemplate, _viewRegistry }) { - return new Renderer(env, rootTemplate, _viewRegistry, false); +export class InertRenderer extends Renderer { + static create({ env, rootTemplate, _viewRegistry }) { + return new this(env, rootTemplate, _viewRegistry, false); + } + + getElement(view) { + throw new Error('Accessing `this.element` is not allowed in non-interactive environments (such as FastBoot).'); + } +} + +export class InteractiveRenderer extends Renderer { + static create({ env, rootTemplate, _viewRegistry }) { + return new this(env, rootTemplate, _viewRegistry, true); } -}; -export const InteractiveRenderer = { - create({ env, rootTemplate, _viewRegistry }) { - return new Renderer(env, rootTemplate, _viewRegistry, true); + getElement(view) { + return getViewElement(view); } -}; +} diff --git a/packages/ember-glimmer/lib/syntax/curly-component.js b/packages/ember-glimmer/lib/syntax/curly-component.js index 7b47d30caf7..84851635bb8 100644 --- a/packages/ember-glimmer/lib/syntax/curly-component.js +++ b/packages/ember-glimmer/lib/syntax/curly-component.js @@ -25,6 +25,9 @@ import { get, _instrumentStart } from 'ember-metal'; +import { + setViewElement +} from 'ember-views'; import processArgs from '../utils/process-args'; import { privatize as P } from 'container'; @@ -234,7 +237,9 @@ class CurlyComponentManager { component.trigger('didInitAttrs', { attrs }); component.trigger('didReceiveAttrs', { newAttrs: attrs }); - component.trigger('willRender'); + if (environment.isInteractive) { + component.trigger('willRender'); + } let bucket = new ComponentStateBucket(environment, component, processedArgs, finalizer); @@ -277,7 +282,7 @@ class CurlyComponentManager { } didCreateElement({ component, classRef, environment }, element, operations) { - component.element = element; + setViewElement(component, element); let { attributeBindings, classNames, classNameBindings } = component; @@ -329,7 +334,7 @@ class CurlyComponentManager { } update(bucket, _, dynamicScope) { - let { component, args, argsRevision } = bucket; + let { component, args, argsRevision, environment } = bucket; bucket.finalizer = _instrumentStart('render.component', rerenderInstrumentDetails, component); @@ -349,8 +354,10 @@ class CurlyComponentManager { component.trigger('didReceiveAttrs', { oldAttrs, newAttrs }); } - component.trigger('willUpdate'); - component.trigger('willRender'); + if (environment.isInteractive) { + component.trigger('willUpdate'); + component.trigger('willRender'); + } } didUpdateLayout(bucket) { @@ -383,11 +390,9 @@ class TopComponentManager extends CurlyComponentManager { component.trigger('didReceiveAttrs'); if (environment.isInteractive) { - component.trigger('willInsertElement'); + component.trigger('willRender'); } - component.trigger('willRender'); - processComponentInitializationAssertions(component, {}); return new ComponentStateBucket(environment, component, args, finalizer); diff --git a/packages/ember-glimmer/tests/integration/components/life-cycle-test.js b/packages/ember-glimmer/tests/integration/components/life-cycle-test.js index a933ab9238a..49b823bb390 100644 --- a/packages/ember-glimmer/tests/integration/components/life-cycle-test.js +++ b/packages/ember-glimmer/tests/integration/components/life-cycle-test.js @@ -2,7 +2,7 @@ import { set, setProperties, run } from 'ember-metal'; import { Component } from '../../utils/helpers'; import { strip } from '../../utils/abstract-test-case'; import { moduleFor, RenderingTest } from '../../utils/test-case'; -import { getViewId } from 'ember-views'; +import { getViewId, getViewElement } from 'ember-views'; class LifeCycleHooksTest extends RenderingTest { constructor() { @@ -92,21 +92,26 @@ class LifeCycleHooksTest extends RenderingTest { } }; - let assertElement = (hookName, instance) => { + let assertElement = (hookName, instance, inDOM = true) => { if (instance.tagName === '') { return; } - this.assert.ok(instance.element, `element property should be present on ${instance} during ${hookName}`); - }; - - let assertElementInDocument = (hookName, instance) => { - if (instance.tagName === '') { return; } + this.assert.ok(getViewElement(instance), `element should be present on ${instance} during ${hookName}`); - this.assert.ok(document.body.contains(instance.element), `element for ${instance} should be in the DOM during ${hookName}`); + if (this.isInteractive) { + this.assert.ok(instance.element, `this.element should be present on ${instance} during ${hookName}`); + this.assert.equal(document.body.contains(instance.element), inDOM, `element for ${instance} ${inDOM ? 'should' : 'should not'} be in the DOM during ${hookName}`); + } else { + this.assert.throws(() => instance.element, /Accessing `this.element` is not allowed in non-interactive environments/); + } }; let assertNoElement = (hookName, instance) => { - if (instance.element) { - this.assert.ok(false, `element should not be present in ${hookName}`); + this.assert.strictEqual(getViewElement(instance), null, `element should not be present in ${hookName}`); + + if (this.isInteractive) { + this.assert.strictEqual(instance.element, null, `this.element should not be present in ${hookName}`); + } else { + this.assert.throws(() => instance.element, /Accessing `this.element` is not allowed in non-interactive environments/); } }; @@ -114,56 +119,68 @@ class LifeCycleHooksTest extends RenderingTest { this.assert.equal(instance._state, expectedState, `within ${hookName} the expected _state is ${expectedState}`); }; + let { isInteractive } = this; + let ComponentClass = this.ComponentClass.extend({ init() { expectDeprecation(() => { this._super(...arguments); }, /didInitAttrs called/); + this.isInitialRender = true; this.componentName = name; pushHook('init'); pushComponent(this); assertParentView('init', this); assertNoElement('init', this); + assertState('init', 'preRender', this); + + run.scheduleOnce('afterRender', () => { + this.isInitialRender = false; + }); }, didInitAttrs(options) { pushHook('didInitAttrs', options); assertParentView('didInitAttrs', this); assertNoElement('didInitAttrs', this); - }, - - didUpdateAttrs(options) { - pushHook('didUpdateAttrs', options); - assertParentView('didUpdateAttrs', this); - }, - - willUpdate(options) { - pushHook('willUpdate', options); - assertParentView('willUpdate', this); + assertState('didInitAttrs', 'preRender', this); }, didReceiveAttrs(options) { pushHook('didReceiveAttrs', options); assertParentView('didReceiveAttrs', this); + + if (this.isInitialRender) { + assertNoElement('didReceiveAttrs', this); + assertState('didReceiveAttrs', 'preRender', this); + } else { + assertElement('didReceiveAttrs', this); + + if (isInteractive) { + assertState('didReceiveAttrs', 'inDOM', this); + } else { + assertState('didReceiveAttrs', 'hasElement', this); + } + } }, willRender() { pushHook('willRender'); assertParentView('willRender', this); - }, - didRender() { - pushHook('didRender'); - assertParentView('didRender', this); - assertElement('didRender', this); - assertElementInDocument('didRender', this); - assertState('didRender', 'inDOM', this); + if (this.isInitialRender) { + assertNoElement('willRender', this); + assertState('willRender', 'preRender', this); + } else { + assertElement('willRender', this); + assertState('willRender', 'inDOM', this); + } }, willInsertElement() { pushHook('willInsertElement'); assertParentView('willInsertElement', this); - assertElement('willInsertElement', this); + assertElement('willInsertElement', this, false); assertState('willInsertElement', 'hasElement', this); }, @@ -171,22 +188,45 @@ class LifeCycleHooksTest extends RenderingTest { pushHook('didInsertElement'); assertParentView('didInsertElement', this); assertElement('didInsertElement', this); - assertElementInDocument('didInsertElement', this); assertState('didInsertElement', 'inDOM', this); }, + didRender() { + pushHook('didRender'); + assertParentView('didRender', this); + assertElement('didRender', this); + assertState('didRender', 'inDOM', this); + }, + + didUpdateAttrs(options) { + pushHook('didUpdateAttrs', options); + assertParentView('didUpdateAttrs', this); + + if (isInteractive) { + assertState('didUpdateAttrs', 'inDOM', this); + } else { + assertState('didUpdateAttrs', 'hasElement', this); + } + }, + + willUpdate(options) { + pushHook('willUpdate', options); + assertParentView('willUpdate', this); + assertElement('willUpdate', this); + assertState('willUpdate', 'inDOM', this); + }, + didUpdate(options) { pushHook('didUpdate', options); assertParentView('didUpdate', this); assertElement('didUpdate', this); - assertElementInDocument('didUpdate', this); + assertState('didUpdate', 'inDOM', this); }, willDestroyElement() { pushHook('willDestroyElement'); assertParentView('willDestroyElement', this); assertElement('willDestroyElement', this); - assertElementInDocument('willDestroyElement', this); assertState('willDestroyElement', 'inDOM', this); }, @@ -194,7 +234,7 @@ class LifeCycleHooksTest extends RenderingTest { pushHook('willClearRender'); assertParentView('willClearRender', this); assertElement('willClearRender', this); - assertElementInDocument('willClearRender', this); + assertState('willClearRender', 'inDOM', this); }, didDestroyElement() { @@ -294,17 +334,14 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'init'], ['the-top', 'didInitAttrs', { attrs: topAttrs }], ['the-top', 'didReceiveAttrs', { newAttrs: topAttrs }], - ['the-top', 'willRender'], ['the-middle', 'init'], ['the-middle', 'didInitAttrs', { attrs: middleAttrs }], ['the-middle', 'didReceiveAttrs', { newAttrs: middleAttrs }], - ['the-middle', 'willRender'], ['the-bottom', 'init'], ['the-bottom', 'didInitAttrs', { attrs: bottomAttrs }], - ['the-bottom', 'didReceiveAttrs', { newAttrs: bottomAttrs }], - ['the-bottom', 'willRender'] + ['the-bottom', 'didReceiveAttrs', { newAttrs: bottomAttrs }] ] }); @@ -338,16 +375,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'didRender'] ], - nonInteractive: [ - ['the-top', 'willUpdate'], - ['the-top', 'willRender'], - - ['the-middle', 'willUpdate'], - ['the-middle', 'willRender'], - - ['the-bottom', 'willUpdate'], - ['the-bottom', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => this.components['the-middle'].rerender()); @@ -375,14 +403,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'didRender'] ], - nonInteractive: [ - // Sync hooks - ['the-top', 'willUpdate'], - ['the-top', 'willRender'], - - ['the-middle', 'willUpdate'], - ['the-middle', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => this.components['the-top'].rerender()); @@ -404,12 +425,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'didRender'] ], - nonInteractive: [ - // Sync hooks - - ['the-top', 'willUpdate'], - ['the-top', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => set(this.context, 'twitter', '@horsetomdale')); @@ -445,10 +461,7 @@ class LifeCycleHooksTest extends RenderingTest { nonInteractive: [ // Sync hooks ['the-top', 'didUpdateAttrs', topAttrs], - ['the-top', 'didReceiveAttrs', topAttrs], - - ['the-top', 'willUpdate'], - ['the-top', 'willRender'] + ['the-top', 'didReceiveAttrs', topAttrs] ] }); @@ -568,22 +581,18 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'init'], ['the-parent', 'didInitAttrs', { attrs: parentAttrs }], ['the-parent', 'didReceiveAttrs', { newAttrs: parentAttrs }], - ['the-parent', 'willRender'], ['the-first-child', 'init'], ['the-first-child', 'didInitAttrs', { attrs: firstAttrs }], ['the-first-child', 'didReceiveAttrs', { newAttrs: firstAttrs }], - ['the-first-child', 'willRender'], ['the-second-child', 'init'], ['the-second-child', 'didInitAttrs', { attrs: secondAttrs }], ['the-second-child', 'didReceiveAttrs', { newAttrs: secondAttrs }], - ['the-second-child', 'willRender'], ['the-last-child', 'init'], ['the-last-child', 'didInitAttrs', { attrs: lastAttrs }], - ['the-last-child', 'didReceiveAttrs', { newAttrs: lastAttrs }], - ['the-last-child', 'willRender'] + ['the-last-child', 'didReceiveAttrs', { newAttrs: lastAttrs }] ] }); @@ -612,15 +621,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'didRender'] ], - nonInteractive: [ - // Sync hooks - - ['the-parent', 'willUpdate'], - ['the-parent', 'willRender'], - - ['the-first-child', 'willUpdate'], - ['the-first-child', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => this.components['the-second-child'].rerender()); @@ -648,15 +649,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'didRender'] ], - nonInteractive: [ - // Sync hooks - - ['the-parent', 'willUpdate'], - ['the-parent', 'willRender'], - - ['the-second-child', 'willUpdate'], - ['the-second-child', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => this.components['the-last-child'].rerender()); @@ -684,15 +677,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'didRender'] ], - nonInteractive: [ - // Sync hooks - - ['the-parent', 'willUpdate'], - ['the-parent', 'willRender'], - - ['the-last-child', 'willUpdate'], - ['the-last-child', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => this.components['the-parent'].rerender()); @@ -714,12 +699,7 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'didRender'] ], - nonInteractive: [ - // Sync hooks - - ['the-parent', 'willUpdate'], - ['the-parent', 'willRender'] - ] + nonInteractive: [] }); this.runTask(() => setProperties(this.context, { @@ -789,26 +769,14 @@ class LifeCycleHooksTest extends RenderingTest { ['the-parent', 'didUpdateAttrs', parentAttrs], ['the-parent', 'didReceiveAttrs', parentAttrs], - ['the-parent', 'willUpdate'], - ['the-parent', 'willRender'], - ['the-first-child', 'didUpdateAttrs', firstAttrs], ['the-first-child', 'didReceiveAttrs', firstAttrs], - ['the-first-child', 'willUpdate'], - ['the-first-child', 'willRender'], - ['the-second-child', 'didUpdateAttrs', secondAttrs], ['the-second-child', 'didReceiveAttrs', secondAttrs], - ['the-second-child', 'willUpdate'], - ['the-second-child', 'willRender'], - ['the-last-child', 'didUpdateAttrs', lastAttrs], - ['the-last-child', 'didReceiveAttrs', lastAttrs], - - ['the-last-child', 'willUpdate'], - ['the-last-child', 'willRender'] + ['the-last-child', 'didReceiveAttrs', lastAttrs] ] }); @@ -921,17 +889,14 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'init'], ['the-top', 'didInitAttrs', { attrs: topAttrs }], ['the-top', 'didReceiveAttrs', { newAttrs: topAttrs }], - ['the-top', 'willRender'], ['the-middle', 'init'], ['the-middle', 'didInitAttrs', { attrs: middleAttrs }], ['the-middle', 'didReceiveAttrs', { newAttrs: middleAttrs }], - ['the-middle', 'willRender'], ['the-bottom', 'init'], ['the-bottom', 'didInitAttrs', { attrs: bottomAttrs }], - ['the-bottom', 'didReceiveAttrs', { newAttrs: bottomAttrs }], - ['the-bottom', 'willRender'] + ['the-bottom', 'didReceiveAttrs', { newAttrs: bottomAttrs }] ] }); @@ -988,20 +953,11 @@ class LifeCycleHooksTest extends RenderingTest { ['the-top', 'didUpdateAttrs', topAttrs], ['the-top', 'didReceiveAttrs', topAttrs], - ['the-top', 'willUpdate'], - ['the-top', 'willRender'], - ['the-middle', 'didUpdateAttrs', middleAttrs], ['the-middle', 'didReceiveAttrs', middleAttrs], - ['the-middle', 'willUpdate'], - ['the-middle', 'willRender'], - ['the-bottom', 'didUpdateAttrs', bottomAttrs], - ['the-bottom', 'didReceiveAttrs', bottomAttrs], - - ['the-bottom', 'willUpdate'], - ['the-bottom', 'willRender'] + ['the-bottom', 'didReceiveAttrs', bottomAttrs] ] }); @@ -1081,20 +1037,24 @@ class LifeCycleHooksTest extends RenderingTest { let ret = [ ['an-item', 'init'], ['an-item', 'didInitAttrs', { attrs: { count } }], - ['an-item', 'didReceiveAttrs', { newAttrs: { count } }], - ['an-item', 'willRender'] + ['an-item', 'didReceiveAttrs', { newAttrs: { count } }] ]; if (this.isInteractive) { - ret.push(['an-item', 'willInsertElement']); + ret.push( + ['an-item', 'willRender'], + ['an-item', 'willInsertElement'] + ); } ret.push( ['nested-item', 'init'], ['nested-item', 'didInitAttrs', { attrs: { } }], - ['nested-item', 'didReceiveAttrs', { newAttrs: { } }], - ['nested-item', 'willRender'] + ['nested-item', 'didReceiveAttrs', { newAttrs: { } }] ); if (this.isInteractive) { - ret.push(['nested-item', 'willInsertElement']); + ret.push( + ['nested-item', 'willRender'], + ['nested-item', 'willInsertElement'] + ); } return ret; }; @@ -1108,7 +1068,7 @@ class LifeCycleHooksTest extends RenderingTest { ['an-item', 'didRender'] ]; } else { - return [ ]; + return []; } }; @@ -1232,12 +1192,10 @@ class LifeCycleHooksTest extends RenderingTest { ['no-items', 'init'], ['no-items', 'didInitAttrs', { attrs: { } }], ['no-items', 'didReceiveAttrs', { newAttrs: { } }], - ['no-items', 'willRender'], ['nested-item', 'init'], ['nested-item', 'didInitAttrs', { attrs: { } }], ['nested-item', 'didReceiveAttrs', { newAttrs: { } }], - ['nested-item', 'willRender'], ['an-item', 'willDestroy'], ['nested-item', 'willDestroy'], diff --git a/packages/ember-views/lib/index.js b/packages/ember-views/lib/index.js index aa1f30fec4f..23338400275 100644 --- a/packages/ember-views/lib/index.js +++ b/packages/ember-views/lib/index.js @@ -11,8 +11,10 @@ export { getViewBoundingClientRect, getRootViews, getChildViews, - STYLE_WARNING, - getViewId + getViewId, + getViewElement, + setViewElement, + STYLE_WARNING } from './system/utils'; export { default as EventDispatcher } from './system/event_dispatcher'; export { default as ComponentLookup } from './component_lookup'; diff --git a/packages/ember-views/lib/mixins/view_support.js b/packages/ember-views/lib/mixins/view_support.js index 46cb0a3b63c..5933ed5315a 100644 --- a/packages/ember-views/lib/mixins/view_support.js +++ b/packages/ember-views/lib/mixins/view_support.js @@ -1,5 +1,5 @@ import { guidFor, symbol } from 'ember-utils'; -import { assert, deprecate, Mixin } from 'ember-metal'; +import { assert, deprecate, descriptor, Mixin } from 'ember-metal'; import { POST_INIT } from 'ember-runtime'; import { environment } from 'ember-environment'; import { matches } from '../system/utils'; @@ -95,7 +95,13 @@ export default Mixin.create({ @type DOMElement @public */ - element: null, + element: descriptor({ + configurable: false, + enumerable: false, + get() { + return this.renderer.getElement(this); + } + }), /** Returns a jQuery object for this view's element. If you pass in a selector diff --git a/packages/ember-views/lib/system/utils.js b/packages/ember-views/lib/system/utils.js index 32f202e0c2b..27dd9ae0996 100644 --- a/packages/ember-views/lib/system/utils.js +++ b/packages/ember-views/lib/system/utils.js @@ -49,8 +49,26 @@ export function getViewId(view) { return view.elementId || guidFor(view); } -export const CHILD_VIEW_IDS = symbol('CHILD_VIEW_IDS'); -export const CHILD_VIEW_COUNTER = symbol('CHILD_VIEW_COUNTER'); +const VIEW_ELEMENT = symbol('VIEW_ELEMENT'); + +/** + @private + @method getViewElement + @param {Ember.View} view + */ +export function getViewElement(view) { + return view[VIEW_ELEMENT]; +} + +export function initViewElement(view) { + view[VIEW_ELEMENT] = null; +} + +export function setViewElement(view, element) { + return view[VIEW_ELEMENT] = element; +} + +const CHILD_VIEW_IDS = symbol('CHILD_VIEW_IDS'); /** @private diff --git a/packages/ember-views/lib/views/core_view.js b/packages/ember-views/lib/views/core_view.js index e26101b6e1e..4a42da8ca5b 100644 --- a/packages/ember-views/lib/views/core_view.js +++ b/packages/ember-views/lib/views/core_view.js @@ -5,6 +5,7 @@ import { deprecateUnderscoreActions, typeOf } from 'ember-runtime'; +import { initViewElement } from '../system/utils'; import { cloneStates, states } from './states'; /** @@ -32,12 +33,8 @@ const CoreView = EmberObject.extend(Evented, ActionHandler, { this._super(...arguments); this._state = 'preRender'; this._currentState = this._states.preRender; - this._willInsert = false; - this.lastResult = null; - this._destroyingSubtreeForView = null; - this._isDispatchingAttrs = false; - this.element = null; - this._env = null; + + initViewElement(this); if (!this.renderer) { throw new Error(`Cannot instantiate a component without a renderer. Please ensure that you are creating ${this} with a proper container/registry.`); diff --git a/packages/ember-views/lib/views/states.js b/packages/ember-views/lib/views/states.js index 2b33158467c..72a1fcc7c5f 100644 --- a/packages/ember-views/lib/views/states.js +++ b/packages/ember-views/lib/views/states.js @@ -22,6 +22,21 @@ export function cloneStates(from) { return into; } +/* + Describe how the specified actions should behave in the various + states that a view can exist in. Possible states: + + * preRender: when a view is first instantiated, and after its + element was destroyed, it is in the preRender state + * hasElement: the DOM representation of the view is created, + and is ready to be inserted + * inDOM: once a view has been inserted into the DOM it is in + the inDOM state. A view spends the vast majority of its + existence in this state. + * destroyed: once a view has been destroyed (using the destroy + method), it is in this state. No further actions can be invoked + on a destroyed view. +*/ export let states = { _default: _default, preRender: preRender, diff --git a/packages/ember-views/lib/views/states/default.js b/packages/ember-views/lib/views/states/default.js index 57be5242a28..80a71290dd2 100644 --- a/packages/ember-views/lib/views/states/default.js +++ b/packages/ember-views/lib/views/states/default.js @@ -1,8 +1,6 @@ import { - Error as EmberError, - get + Error as EmberError } from 'ember-metal'; -import { MUTABLE_CELL } from '../../compat/attrs'; /** @module ember @@ -18,23 +16,6 @@ export default { return undefined; }, - getElement() { - return null; - }, - - legacyPropertyDidChange(view, key) { - let attrs = view.attrs; - if (attrs && key in attrs) { - let possibleCell = attrs[key]; - - if (possibleCell && possibleCell[MUTABLE_CELL]) { - let value = get(view, key); - if (value === possibleCell.value) { return; } - possibleCell.update(value); - } - } - }, - // Handle events from `Ember.EventDispatcher` handleEvent() { return true; // continue event propagation diff --git a/packages/ember-views/lib/views/states/has_element.js b/packages/ember-views/lib/views/states/has_element.js index a53e8934b99..dce64f9f279 100644 --- a/packages/ember-views/lib/views/states/has_element.js +++ b/packages/ember-views/lib/views/states/has_element.js @@ -1,6 +1,6 @@ import { assign } from 'ember-utils'; import _default from './default'; -import { run, flaggedInstrument, get } from 'ember-metal'; +import { run, flaggedInstrument } from 'ember-metal'; import jQuery from '../../system/jquery'; const hasElement = Object.create(_default); @@ -11,13 +11,6 @@ assign(hasElement, { return sel ? jQuery(sel, elem) : jQuery(elem); }, - getElement(view) { - let parent = get(view, 'parentView'); - if (parent) { parent = get(parent, 'element'); } - if (parent) { return view.findElementInParentElement(parent); } - return jQuery('#' + get(view, 'elementId'))[0]; - }, - // once the view has been inserted into the DOM, rerendering is // deferred to allow bindings to synchronize. rerender(view) { diff --git a/packages/ember-views/lib/views/states/pre_render.js b/packages/ember-views/lib/views/states/pre_render.js index d55d6f65a48..f927f611342 100644 --- a/packages/ember-views/lib/views/states/pre_render.js +++ b/packages/ember-views/lib/views/states/pre_render.js @@ -1,4 +1,3 @@ -import { assign } from 'ember-utils'; import _default from './default'; /** @@ -6,10 +5,4 @@ import _default from './default'; @submodule ember-views */ -let preRender = Object.create(_default); - -assign(preRender, { - legacyPropertyDidChange(view, key) {} -}); - -export default preRender; +export default Object.create(_default); diff --git a/packages/ember-views/lib/views/view.js b/packages/ember-views/lib/views/view.js index da412f82563..047433b9881 100644 --- a/packages/ember-views/lib/views/view.js +++ b/packages/ember-views/lib/views/view.js @@ -1,11 +1,3 @@ -import '../system/ext'; // for the side effect of extending Ember.run.queues - -import CoreView from './core_view'; -import ViewChildViewsSupport from '../mixins/child_views_support'; -import ViewStateSupport from '../mixins/view_state_support'; -import ClassNamesSupport from '../mixins/class_names_support'; -import ViewMixin from '../mixins/view_support'; - /** @module ember @submodule ember-views @@ -492,47 +484,8 @@ import ViewMixin from '../mixins/view_support'; @extends Ember.CoreView @deprecated See http://emberjs.com/deprecations/v1.x/#toc_ember-view @uses Ember.ViewSupport - @uses Ember.ViewChildViewsSupport + @uses Ember.ChildViewsSupport @uses Ember.ClassNamesSupport @uses Ember.AttributeBindingsSupport - @public -*/ -// jscs:disable validateIndentation -var View = CoreView.extend( - ViewChildViewsSupport, - ViewStateSupport, - ClassNamesSupport, - ViewMixin); - -// jscs:enable validateIndentation - -/* - Describe how the specified actions should behave in the various - states that a view can exist in. Possible states: - - * preRender: when a view is first instantiated, and after its - element was destroyed, it is in the preRender state - * inBuffer: once a view has been rendered, but before it has - been inserted into the DOM, it is in the inBuffer state - * hasElement: the DOM representation of the view is created, - and is ready to be inserted - * inDOM: once a view has been inserted into the DOM it is in - the inDOM state. A view spends the vast majority of its - existence in this state. - * destroyed: once a view has been destroyed (using the destroy - method), it is in this state. No further actions can be invoked - on a destroyed view. + @private */ - -// in the destroyed state, everything is illegal - -// before rendering has begun, all legal manipulations are noops. - -// inside the buffer, legal manipulations are done on the buffer - -// once the view has been inserted into the DOM, legal manipulations -// are done on the DOM element. - -export default View; - -export { ViewChildViewsSupport, ViewStateSupport, ClassNamesSupport }; diff --git a/packages/ember/lib/index.js b/packages/ember/lib/index.js index cefa62c1dd3..b2271233a02 100644 --- a/packages/ember/lib/index.js +++ b/packages/ember/lib/index.js @@ -467,8 +467,7 @@ import { makeBoundHelper, getTemplates, setTemplates, - _getSafeString, - Renderer + _getSafeString } from 'ember-glimmer'; Ember.Component = Component; @@ -478,7 +477,6 @@ Ember.Checkbox = Checkbox; Ember.TextField = TextField; Ember.TextArea = TextArea; Ember.LinkComponent = LinkComponent; -Ember._Renderer = Renderer; if (ENV.EXTEND_PROTOTYPES.String) { String.prototype.htmlSafe = function() { @@ -552,6 +550,7 @@ Ember.ViewTargetActionSupport = views.ViewTargetActionSupport; Ember.ViewUtils = { isSimpleClick: views.isSimpleClick, + getViewElement: views.getViewElement, getViewBounds: views.getViewBounds, getViewClientRects: views.getViewClientRects, getViewBoundingClientRect: views.getViewBoundingClientRect, diff --git a/packages/ember/tests/reexports_test.js b/packages/ember/tests/reexports_test.js index d6b024ea732..a42aaf40dc8 100644 --- a/packages/ember/tests/reexports_test.js +++ b/packages/ember/tests/reexports_test.js @@ -121,6 +121,7 @@ QUnit.module('ember reexports'); // ember-views ['$', 'ember-views', 'jQuery'], ['ViewUtils.isSimpleClick', 'ember-views', 'isSimpleClick'], + ['ViewUtils.getViewElement', 'ember-views', 'getViewElement'], ['ViewUtils.getViewBounds', 'ember-views', 'getViewBounds'], ['ViewUtils.getViewClientRects', 'ember-views', 'getViewClientRects'], ['ViewUtils.getViewBoundingClientRect', 'ember-views', 'getViewBoundingClientRect'], @@ -131,7 +132,6 @@ QUnit.module('ember reexports'); ['EventDispatcher', 'ember-views'], // ember-glimmer - ['_Renderer', 'ember-glimmer', 'Renderer'], ['Component', 'ember-glimmer', 'Component'], ['Helper', 'ember-glimmer', 'Helper'], ['Helper.helper', 'ember-glimmer', 'helper'], diff --git a/tests/node/app-boot-test.js b/tests/node/app-boot-test.js index 2b80892044f..914ec5e900d 100644 --- a/tests/node/app-boot-test.js +++ b/tests/node/app-boot-test.js @@ -82,19 +82,22 @@ QUnit.test("outlets", function(assert) { QUnit.test("lifecycle hooks disabled", function(assert) { assert.expect(1); - this.template('application', "{{my-component}}{{outlet}}"); + this.template('application', "{{my-component foo='bar'}}{{outlet}}"); this.component('my-component', { - willRender: function() { - assert.ok(true, "should trigger component willRender hook"); + didReceiveAttrs() { + assert.ok(true, "should trigger didReceiveAttrs hook"); }, - didRender: function() { + willRender() { + assert.ok(false, "should not trigger willRender hook"); + }, + didRender() { assert.ok(false, "should not trigger didRender hook"); }, - willInsertElement: function() { + willInsertElement() { assert.ok(false, "should not trigger willInsertElement hook"); }, - didInsertElement: function() { + didInsertElement() { assert.ok(false, "should not trigger didInsertElement hook"); } });