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 0be07a7211a..e496d519e1d 100644 --- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js +++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js @@ -73,7 +73,9 @@ ComponentNodeManager.create = function ComponentNodeManager_create(renderNode, e // If the component specifies its layout via the `layout` property // instead of using the template looked up in the container, get it // now that we have the component instance. - layout = get(component, 'layout') || layout; + if (!layout) { + layout = get(component, 'layout'); + } runInDebug(() => { if (isAngleBracket) { diff --git a/packages/ember-routing-views/lib/components/link-to.js b/packages/ember-routing-views/lib/components/link-to.js index 9fc439968ae..43700e202ba 100644 --- a/packages/ember-routing-views/lib/components/link-to.js +++ b/packages/ember-routing-views/lib/components/link-to.js @@ -344,7 +344,7 @@ linkToTemplate.meta.revision = 'Ember@VERSION_STRING_PLACEHOLDER'; @private **/ let LinkComponent = EmberComponent.extend({ - defaultLayout: linkToTemplate, + layout: linkToTemplate, tagName: 'a', diff --git a/packages/ember-views/lib/components/component.js b/packages/ember-views/lib/components/component.js index 94c09a43d1a..17f0eece4cb 100644 --- a/packages/ember-views/lib/components/component.js +++ b/packages/ember-views/lib/components/component.js @@ -1,5 +1,5 @@ import Ember from 'ember-metal/core'; -import { assert } from 'ember-metal/debug'; +import { assert, deprecate } from 'ember-metal/debug'; import TargetActionSupport from 'ember-runtime/mixins/target_action_support'; import View from 'ember-views/views/view'; @@ -132,12 +132,33 @@ var Component = View.extend(TargetActionSupport, { }), init() { - this._super.apply(this, arguments); + this._super(...arguments); set(this, 'controller', this); set(this, 'context', this); + + if (!this.layout && this.layoutName && this.container) { + let layoutName = get(this, 'layoutName'); + + this.layout = this.templateForName(layoutName); + } + + // If a `defaultLayout` was specified move it to the `layout` prop. + // `layout` is no longer a CP, so this just ensures that the `defaultLayout` + // logic is supported with a deprecation + if (this.defaultLayout && !this.layout) { + deprecate( + `Specifying \`defaultLayout\` to ${this} is deprecated. Please use \`layout\` instead.`, + false, + { id: 'ember-views.component.defaultLayout', until: '3.0.0' } + ); + + this.layout = this.defaultLayout; + } }, template: null, + layoutName: null, + layout: null, /** If the component is currently inserted into the DOM of a parent view, this diff --git a/packages/ember-views/tests/views/component_test.js b/packages/ember-views/tests/views/component_test.js index f45f4b1246d..5a144f622c6 100644 --- a/packages/ember-views/tests/views/component_test.js +++ b/packages/ember-views/tests/views/component_test.js @@ -62,6 +62,14 @@ QUnit.test('Specifying both templateName and layoutName to a component is NOT de equal(get(component, 'layoutName'), 'hum-drum'); }); +QUnit.test('Specifying a defaultLayout to a component is deprecated', function() { + expectDeprecation(function() { + Component.extend({ + defaultLayout: 'hum-drum' + }).create(); + }, /Specifying `defaultLayout` to .+ is deprecated\./); +}); + QUnit.test('Specifying a templateName on a component with a layoutName specified in a superclass is NOT deprecated', function() { expectNoDeprecation(); var Parent = Component.extend({ diff --git a/packages/ember/tests/component_registration_test.js b/packages/ember/tests/component_registration_test.js index c3a7251cb83..56e178587f1 100644 --- a/packages/ember/tests/component_registration_test.js +++ b/packages/ember/tests/component_registration_test.js @@ -134,7 +134,7 @@ QUnit.test('Component-like invocations are treated as bound paths if neither tem equal(Ember.$('#wrapper').text(), 'machty hello world', 'The component is composed correctly'); }); -QUnit.test('Assigning templateName to a component should setup the template as a layout', function() { +QUnit.test('Assigning layoutName to a component should setup the template as a layout', function() { expect(1); Ember.TEMPLATES.application = compile('
{{#my-component}}{{text}}{{/my-component}}
'); @@ -154,6 +154,70 @@ QUnit.test('Assigning templateName to a component should setup the template as a equal(Ember.$('#wrapper').text(), 'inner-outer', 'The component is composed correctly'); }); +QUnit.test('Assigning layoutName and layout to a component should use the `layout` value', function() { + expect(1); + + Ember.TEMPLATES.application = compile('
{{#my-component}}{{text}}{{/my-component}}
'); + Ember.TEMPLATES['foo-bar-baz'] = compile('No way!'); + + boot(function() { + registry.register('controller:application', Ember.Controller.extend({ + 'text': 'outer' + })); + + registry.register('component:my-component', Ember.Component.extend({ + text: 'inner', + layoutName: 'foo-bar-baz', + layout: compile('{{text}}-{{yield}}') + })); + }); + + equal(Ember.$('#wrapper').text(), 'inner-outer', 'The component is composed correctly'); +}); + +QUnit.test('Assigning defaultLayout to a component should set it up as a layout if no layout was found [DEPRECATED]', function() { + expect(2); + + Ember.TEMPLATES.application = compile('
{{#my-component}}{{text}}{{/my-component}}
'); + + expectDeprecation(function() { + boot(function() { + registry.register('controller:application', Ember.Controller.extend({ + 'text': 'outer' + })); + + registry.register('component:my-component', Ember.Component.extend({ + text: 'inner', + defaultLayout: compile('{{text}}-{{yield}}') + })); + }); + }, /Specifying `defaultLayout` to .+ is deprecated\./); + + equal(Ember.$('#wrapper').text(), 'inner-outer', 'The component is composed correctly'); +}); + +QUnit.test('Assigning defaultLayout to a component should set it up as a layout if layout was found [DEPRECATED]', function() { + expect(2); + + Ember.TEMPLATES.application = compile('
{{#my-component}}{{text}}{{/my-component}}
'); + Ember.TEMPLATES['components/my-component'] = compile('{{text}}-{{yield}}'); + + expectDeprecation(function() { + boot(function() { + registry.register('controller:application', Ember.Controller.extend({ + 'text': 'outer' + })); + + registry.register('component:my-component', Ember.Component.extend({ + text: 'inner', + defaultLayout: compile('should not see this!') + })); + }); + }, /Specifying `defaultLayout` to .+ is deprecated\./); + + equal(Ember.$('#wrapper').text(), 'inner-outer', 'The component is composed correctly'); +}); + QUnit.test('Using name of component that does not exist', function () { Ember.TEMPLATES.application = compile('
{{#no-good}} {{/no-good}}
');