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 0bcb011be41..1cbec43cc79 100644
--- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
+++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
@@ -6,6 +6,7 @@ import { get } from 'ember-metal/property_get';
import { set } from 'ember-metal/property_set';
import setProperties from 'ember-metal/set_properties';
import { MUTABLE_CELL } from 'ember-views/compat/attrs-proxy';
+import { HAS_BLOCK } from 'ember-views/system/link-to';
import { instrument } from 'ember-htmlbars/system/instrumentation-support';
import LegacyEmberComponent from 'ember-views/components/component';
import GlimmerComponent from 'ember-htmlbars/glimmer-component';
@@ -45,7 +46,10 @@ ComponentNodeManager.create = function(renderNode, env, options) {
component = component || (isAngleBracket ? GlimmerComponent : LegacyEmberComponent);
- let createOptions = { parentView };
+ let createOptions = {
+ parentView,
+ [HAS_BLOCK]: !!templates.default
+ };
configureTagName(attrs, tagName, component, isAngleBracket, createOptions);
@@ -65,8 +69,8 @@ ComponentNodeManager.create = function(renderNode, env, options) {
// Instantiate the component
component = createComponent(component, isAngleBracket, createOptions, renderNode, env, attrs);
- // If the component specifies its template via the `layout properties
- // instead of using the template looked up in the container, get them
+ // 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;
diff --git a/packages/ember-routing-htmlbars/lib/keywords/link-to.js b/packages/ember-routing-htmlbars/lib/keywords/link-to.js
index 8ee162ce0a2..26097642f2a 100644
--- a/packages/ember-routing-htmlbars/lib/keywords/link-to.js
+++ b/packages/ember-routing-htmlbars/lib/keywords/link-to.js
@@ -3,9 +3,8 @@
@submodule ember-routing-htmlbars
*/
-import { readArray } from 'ember-metal/streams/utils';
import Ember from 'ember-metal/core'; // assert
-import merge from 'ember-metal/merge';
+import { RELATED_VIEW } from 'ember-views/system/link-to';
/**
The `{{link-to}}` helper renders a link to the supplied
@@ -315,19 +314,13 @@ export default {
},
render(morph, env, scope, params, hash, template, inverse, visitor) {
- var attrs = merge({}, hash);
-
- // TODO: Rewrite link-to to use arbitrary length positional params.
- attrs.params = readArray(params);
-
- // Used for deprecations (to tell the user what view the deprecated syntax
- // was used in).
- attrs.view = env.view;
-
- // TODO: Remove once `hasBlock` is working again
- attrs.hasBlock = !!template;
+ Ember.runInDebug(() => {
+ // Used for deprecations (to tell the user what view the deprecated syntax was used in).
+ // Until: 3.0.0
+ hash[RELATED_VIEW] = env.view;
+ });
- env.hooks.component(morph, env, scope, '-link-to', params, attrs, { default: template }, visitor);
+ env.hooks.component(morph, env, scope, '-link-to', params, hash, { default: template }, visitor);
},
rerender(morph, env, scope, params, hash, template, inverse, visitor) {
diff --git a/packages/ember-routing-htmlbars/tests/helpers/link-to_test.js b/packages/ember-routing-htmlbars/tests/helpers/link-to_test.js
index 89c3dd294d1..c9e83b5dca4 100644
--- a/packages/ember-routing-htmlbars/tests/helpers/link-to_test.js
+++ b/packages/ember-routing-htmlbars/tests/helpers/link-to_test.js
@@ -29,6 +29,7 @@ registry.register('service:-routing', EmberObject.extend({
registry.register('component-lookup:main', ComponentLookup);
registry.register('component:-link-to', LinkComponent);
+registry.register('component:custom-link-to', LinkComponent.extend());
QUnit.module('ember-routing-htmlbars: link-to helper', {
setup() {
@@ -145,3 +146,15 @@ QUnit.test('unwraps controllers', function() {
equal(view.$().text(), 'Text');
});
+
+QUnit.test('able to safely extend the built-in component and use the normal path', function() {
+ view = EmberView.create({
+ title: 'my custom link-to component',
+ template: compile('{{custom-link-to view.title}}'),
+ container: container
+ });
+
+ runAppend(view);
+
+ equal(view.$().text(), 'my custom link-to component', 'rendered a custom-link-to component');
+});
diff --git a/packages/ember-routing-views/lib/views/link.js b/packages/ember-routing-views/lib/views/link.js
index 83b8cff1b73..05d4e3416e6 100644
--- a/packages/ember-routing-views/lib/views/link.js
+++ b/packages/ember-routing-views/lib/views/link.js
@@ -14,6 +14,7 @@ import EmberComponent from 'ember-views/components/component';
import inject from 'ember-runtime/inject';
import 'ember-runtime/system/service'; // creates inject.service
import ControllerMixin from 'ember-runtime/mixins/controller';
+import { HAS_BLOCK, RELATED_VIEW } from 'ember-views/system/link-to';
import linkToTemplate from 'ember-htmlbars/templates/link-to';
linkToTemplate.meta.revision = 'Ember@VERSION_STRING_PLACEHOLDER';
@@ -365,7 +366,7 @@ var LinkComponent = EmberComponent.extend({
if (lastParam && lastParam.isQueryParams) {
params.pop();
}
- let onlyQueryParamsSupplied = (this.attrs.hasBlock ? params.length === 0 : params.length === 1);
+ let onlyQueryParamsSupplied = (this[HAS_BLOCK] ? params.length === 0 : params.length === 1);
if (onlyQueryParamsSupplied) {
var appController = this.container.lookup('controller:application');
if (appController) {
@@ -416,8 +417,7 @@ var LinkComponent = EmberComponent.extend({
this.set('disabled', attrs.disabledWhen);
}
- // TODO: Change to built-in hasBlock once it's available
- if (!attrs.hasBlock) {
+ if (!this[HAS_BLOCK]) {
this.set('linkTitle', params.shift());
}
@@ -431,7 +431,7 @@ var LinkComponent = EmberComponent.extend({
while (ControllerMixin.detect(value)) {
Ember.deprecate(
'Providing `{{link-to}}` with a param that is wrapped in a controller is deprecated. ' +
- 'Please update `' + attrs.view + '` to use `{{link-to "post" someController.model}}` instead.',
+ (attrs[RELATED_VIEW] ? 'Please update `' + attrs[RELATED_VIEW] + '` to use `{{link-to "post" someController.model}}` instead.' : ''),
false,
{ id: 'ember-routing-views.controller-wrapped-param', until: '3.0.0' }
);
@@ -503,4 +503,8 @@ function getResolvedQueryParams(queryParamsObject, targetRouteName) {
return resolvedQueryParams;
}
+LinkComponent.reopenClass({
+ positionalParams: 'params'
+});
+
export default LinkComponent;
diff --git a/packages/ember-views/lib/system/link-to.js b/packages/ember-views/lib/system/link-to.js
new file mode 100644
index 00000000000..d12ab6e8ebf
--- /dev/null
+++ b/packages/ember-views/lib/system/link-to.js
@@ -0,0 +1,5 @@
+import { symbol } from 'ember-metal/utils';
+
+// These symbols will be used to limit link-to's public API surface area.
+export let HAS_BLOCK = symbol('HAS_BLOCK');
+export let RELATED_VIEW = symbol('RELATED_VIEW');