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 e59a876a0eb..49421a8c8ff 100644 --- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js +++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js @@ -65,6 +65,14 @@ ComponentNodeManager.create = function(renderNode, env, options) { createOptions._controller = getValue(parentScope.locals.controller); } + // this flag is set when a block was provided so that components can see if + // `this.get('template')` is truthy. this is added for backwards compat only + // and accessing `template` prop on a component will trigger a deprecation + // 2.0TODO: remove + if (templates.default) { + createOptions._deprecatedFlagForBlockProvided = true; + } + // Instantiate the component component = createComponent(component, isAngleBracket, createOptions, renderNode, env, attrs); @@ -103,7 +111,8 @@ function extractComponentTemplates(component, _templates) { // 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'); + let hasBlock = _templates && _templates.default; + let componentTemplate = hasBlock ? null : get(component, '_template'); let layout, templates; if (componentLayout) { @@ -126,7 +135,7 @@ function extractLegacyTemplate(_templates, componentTemplate) { // There is no block template provided but the component has a // `template` property. - if ((!templates || !templates.default) && componentTemplate) { + if ((!_templates || !_templates.default) && componentTemplate) { Ember.deprecate("Using deprecated `template` property on a Component."); templates = { default: componentTemplate.raw }; } else { diff --git a/packages/ember-htmlbars/lib/node-managers/view-node-manager.js b/packages/ember-htmlbars/lib/node-managers/view-node-manager.js index 76d1d2b0bbb..b4dd7899112 100644 --- a/packages/ember-htmlbars/lib/node-managers/view-node-manager.js +++ b/packages/ember-htmlbars/lib/node-managers/view-node-manager.js @@ -60,14 +60,15 @@ ViewNodeManager.create = function(renderNode, env, attrs, found, parentView, pat if (layout) { componentInfo.layout = layout; if (!contentTemplate) { - let template = get(component, 'template'); + let template = getTemplate(component); + if (template) { Ember.deprecate("Using deprecated `template` property on a " + (component.isView ? 'View' : 'Component') + "."); contentTemplate = template.raw; } } } else { - componentInfo.layout = get(component, 'template') || componentInfo.layout; + componentInfo.layout = getTemplate(component) || componentInfo.layout; } renderNode.emberView = component; @@ -148,6 +149,10 @@ ViewNodeManager.prototype.rerender = function(env, attrs, visitor) { }, this); }; +function getTemplate(componentOrView) { + return componentOrView.isComponent ? get(componentOrView, '_template') : get(componentOrView, 'template'); +} + export function createOrUpdateComponent(component, options, createOptions, renderNode, env, attrs = {}) { let snapshot = takeSnapshot(attrs); let props = merge({}, options); diff --git a/packages/ember-htmlbars/tests/helpers/-html-safe-test.js b/packages/ember-htmlbars/tests/helpers/-html-safe-test.js index e09d3ab34ee..0b14717174d 100644 --- a/packages/ember-htmlbars/tests/helpers/-html-safe-test.js +++ b/packages/ember-htmlbars/tests/helpers/-html-safe-test.js @@ -33,7 +33,7 @@ QUnit.test('adds the attribute to the element', function() { component = Component.create({ container, - template: compile(`
`) + layout: compile(``) }); runAppend(component); @@ -43,11 +43,11 @@ QUnit.test('adds the attribute to the element', function() { if (!EmberDev.runningProdBuild) { - QUnit.test('adds the attribute to the element', function() { + QUnit.test('no warnings are triggered from setting style attribute', function() { component = Component.create({ container, - template: compile(``) + layout: compile(``) }); runAppend(component); diff --git a/packages/ember-htmlbars/tests/integration/component_invocation_test.js b/packages/ember-htmlbars/tests/integration/component_invocation_test.js index 0c3900d955b..64e949c50b6 100644 --- a/packages/ember-htmlbars/tests/integration/component_invocation_test.js +++ b/packages/ember-htmlbars/tests/integration/component_invocation_test.js @@ -248,6 +248,79 @@ QUnit.test('with ariaRole specified', function() { equal(view.$('#aria-test').attr('role'), 'main', 'role attribute is applied'); }); +QUnit.test('`template` is true when block supplied', function() { + expect(3); + + let innerComponent; + registry.register('component:with-block', Component.extend({ + init() { + this._super(...arguments); + innerComponent = this; + } + })); + + view = EmberView.extend({ + template: compile('{{#with-block}}In template{{/with-block}}'), + container: container + }).create(); + + runAppend(view); + + equal(jQuery('#qunit-fixture').text(), 'In template'); + + let template; + expectDeprecation(function() { + template = get(innerComponent, 'template'); + }, /Accessing 'template' in .+ is deprecated. To determine if a block was specified to .+ please use '{{#if hasBlock}}' in the components layout./); + + + ok(template, 'template property is truthy when a block was provided'); +}); + +QUnit.test('`template` is false when no block supplied', function() { + expect(2); + + let innerComponent; + registry.register('component:without-block', Component.extend({ + init() { + this._super(...arguments); + innerComponent = this; + } + })); + + view = EmberView.extend({ + template: compile('{{without-block}}'), + container: container + }).create(); + + runAppend(view); + + let template; + expectDeprecation(function() { + template = get(innerComponent, 'template'); + }, /Accessing 'template' in .+ is deprecated. To determine if a block was specified to .+ please use '{{#if hasBlock}}' in the components layout./); + + ok(!template, 'template property is falsey when a block was not provided'); +}); + +QUnit.test('`template` specified in a component is overridden by block', function() { + expect(1); + + registry.register('component:with-block', Component.extend({ + layout: compile('{{yield}}'), + template: compile('Oh, noes!') + })); + + view = EmberView.extend({ + template: compile('{{#with-block}}Whoop, whoop!{{/with-block}}'), + container: container + }).create(); + + runAppend(view); + + equal(view.$().text(), 'Whoop, whoop!', 'block provided always overrides template property'); +}); + if (Ember.FEATURES.isEnabled('ember-views-component-block-info')) { QUnit.test('hasBlock is true when block supplied', function() { expect(1); diff --git a/packages/ember-metal-views/lib/renderer.js b/packages/ember-metal-views/lib/renderer.js index d5098f89131..bfa37b29b3a 100755 --- a/packages/ember-metal-views/lib/renderer.js +++ b/packages/ember-metal-views/lib/renderer.js @@ -20,7 +20,7 @@ Renderer.prototype.prerenderTopLevelView = view._renderNode = renderNode; var layout = get(view, 'layout'); - var template = get(view, 'template'); + var template = view.isComponent ? get(view, '_template') : get(view, 'template'); var componentInfo = { component: view, layout: layout }; diff --git a/packages/ember-views/lib/views/component.js b/packages/ember-views/lib/views/component.js index 39c1707f351..118379a764d 100644 --- a/packages/ember-views/lib/views/component.js +++ b/packages/ember-views/lib/views/component.js @@ -114,7 +114,6 @@ function validateAction(component, actionName) { */ var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, { isComponent: true, - /* This is set so that the proto inspection in appendTemplatedView does not think that it should set the components `context` to that of the parent view. @@ -154,8 +153,23 @@ var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, { @deprecated @property template */ - template: computed('templateName', { + template: computed('_template', { + get() { + Ember.deprecate(`Accessing 'template' in ${this} is deprecated. To determine if a block was specified to ${this} please use '{{#if hasBlock}}' in the components layout.`); + + return get(this, '_template'); + }, + + set(key, value) { + return set(this, '_template', value); + } + }), + + _template: computed('templateName', { get() { + if (get(this, '_deprecatedFlagForBlockProvided')) { + return true; + } var templateName = get(this, 'templateName'); var template = this.templateForName(templateName, 'template');