diff --git a/packages/ember-routing-views/lib/components/link-to.js b/packages/ember-routing-views/lib/components/link-to.js
index ad0fad23376..bb497dc196f 100644
--- a/packages/ember-routing-views/lib/components/link-to.js
+++ b/packages/ember-routing-views/lib/components/link-to.js
@@ -623,14 +623,16 @@ let LinkComponent = EmberComponent.extend({
_invoke(event) {
if (!isSimpleClick(event)) { return true; }
- if (this.attrs.preventDefault !== false) {
- let targetAttribute = this.attrs.target;
+ let preventDefault = get(this, 'preventDefault');
+ let targetAttribute = get(this, 'target');
+
+ if (preventDefault !== false) {
if (!targetAttribute || targetAttribute === '_self') {
event.preventDefault();
}
}
- if (this.attrs.bubbles === false) { event.stopPropagation(); }
+ if (get(this, 'bubbles') === false) { event.stopPropagation(); }
if (get(this, '_isDisabled')) { return false; }
@@ -639,8 +641,7 @@ let LinkComponent = EmberComponent.extend({
return false;
}
- let targetAttribute2 = this.attrs.target;
- if (targetAttribute2 && targetAttribute2 !== '_self') {
+ if (targetAttribute && targetAttribute !== '_self') {
return false;
}
@@ -648,7 +649,7 @@ let LinkComponent = EmberComponent.extend({
let qualifiedRouteName = get(this, 'qualifiedRouteName');
let models = get(this, 'models');
let queryParamValues = get(this, 'queryParams.values');
- let shouldReplace = get(this, 'attrs.replace');
+ let shouldReplace = get(this, 'replace');
routing.transitionTo(qualifiedRouteName, models, queryParamValues, shouldReplace);
},
@@ -656,7 +657,7 @@ let LinkComponent = EmberComponent.extend({
queryParams: null,
qualifiedRouteName: computed('targetRouteName', '_routing.currentState', function computeLinkToComponentQualifiedRouteName() {
- let params = this.attrs.params.slice();
+ let params = get(this, 'params').slice();
let lastParam = params[params.length - 1];
if (lastParam && lastParam.isQueryParams) {
params.pop();
@@ -738,15 +739,14 @@ let LinkComponent = EmberComponent.extend({
willRender() {
let queryParams;
- let attrs = this.attrs;
-
// Do not mutate params in place
- let params = attrs.params.slice();
+ let params = get(this, 'params').slice();
assert('You must provide one or more parameters to the link-to component.', params.length);
- if (attrs.disabledWhen) {
- this.set('disabled', attrs.disabledWhen);
+ let disabledWhen = get(this, 'disabledWhen');
+ if (disabledWhen) {
+ this.set('disabled', disabledWhen);
}
// Process the positional arguments, in order.
diff --git a/packages/ember/tests/helpers/link_to_test.js b/packages/ember/tests/helpers/link_to_test.js
index e5435a64ece..986c64bfeda 100644
--- a/packages/ember/tests/helpers/link_to_test.js
+++ b/packages/ember/tests/helpers/link_to_test.js
@@ -189,6 +189,62 @@ QUnit.test('The {{link-to}} helper supports URL replacement', function() {
equal(replaceCount, 1, 'replaceURL should be called once');
});
+QUnit.test('The {{link-to}} helper supports URL replacement via replace=boundTruthyThing', function() {
+ Ember.TEMPLATES.index = compile('
Home
{{#link-to \'about\' id=\'about-link\' replace=boundTruthyThing}}About{{/link-to}}');
+
+ App.IndexController = Controller.extend({
+ boundTruthyThing: true
+ });
+
+ Router.map(function() {
+ this.route('about');
+ });
+
+ bootApplication();
+
+ run(function() {
+ router.handleURL('/');
+ });
+
+ equal(updateCount, 0, 'precond: setURL has not been called');
+ equal(replaceCount, 0, 'precond: replaceURL has not been called');
+
+ run(function() {
+ jQuery('#about-link', '#qunit-fixture').click();
+ });
+
+ equal(updateCount, 0, 'setURL should not be called');
+ equal(replaceCount, 1, 'replaceURL should be called once');
+});
+
+QUnit.test('The {{link-to}} helper supports setting replace=boundFalseyThing', function() {
+ Ember.TEMPLATES.index = compile('Home
{{#link-to \'about\' id=\'about-link\' replace=boundFalseyThing}}About{{/link-to}}');
+
+ App.IndexController = Controller.extend({
+ boundFalseyThing: false
+ });
+
+ Router.map(function() {
+ this.route('about');
+ });
+
+ bootApplication();
+
+ run(function() {
+ router.handleURL('/');
+ });
+
+ equal(updateCount, 0, 'precond: setURL has not been called');
+ equal(replaceCount, 0, 'precond: replaceURL has not been called');
+
+ run(function() {
+ jQuery('#about-link', '#qunit-fixture').click();
+ });
+
+ equal(updateCount, 1, 'setURL should be called');
+ equal(replaceCount, 0, 'replaceURL should not be called');
+});
+
QUnit.test('the {{link-to}} helper doesn\'t add an href when the tagName isn\'t \'a\'', function() {
Ember.TEMPLATES.index = compile('{{#link-to \'about\' id=\'about-link\' tagName=\'div\'}}About{{/link-to}}');
@@ -207,9 +263,14 @@ QUnit.test('the {{link-to}} helper doesn\'t add an href when the tagName isn\'t
QUnit.test('the {{link-to}} applies a \'disabled\' class when disabled', function () {
- Ember.TEMPLATES.index = compile('{{#link-to "about" id="about-link" disabledWhen="shouldDisable"}}About{{/link-to}}');
+ Ember.TEMPLATES.index = compile(`
+ {{#link-to "about" id="about-link-static" disabledWhen="shouldDisable"}}About{{/link-to}}
+ {{#link-to "about" id="about-link-dynamic" disabledWhen=dynamicDisabledWhen}}About{{/link-to}}
+ `);
+
App.IndexController = Controller.extend({
- shouldDisable: true
+ shouldDisable: true,
+ dynamicDisabledWhen: 'shouldDisable'
});
Router.map(function() {
@@ -222,7 +283,8 @@ QUnit.test('the {{link-to}} applies a \'disabled\' class when disabled', functio
router.handleURL('/');
});
- equal(jQuery('#about-link.disabled', '#qunit-fixture').length, 1, 'The link is disabled when its disabledWhen is true');
+ equal(jQuery('#about-link-static.disabled', '#qunit-fixture').length, 1, 'The static link is disabled when its disabledWhen is true');
+ equal(jQuery('#about-link-dynamic.disabled', '#qunit-fixture').length, 1, 'The dynamic link is disabled when its disabledWhen is true');
});
QUnit.test('the {{link-to}} doesn\'t apply a \'disabled\' class if disabledWhen is not provided', function () {
@@ -605,6 +667,45 @@ QUnit.test('The {{link-to}} helper supports bubbles=false', function() {
equal(hidden, 0, 'The link didn\'t bubble');
});
+QUnit.test('The {{link-to}} helper supports bubbles=boundFalseyThing', function() {
+ Ember.TEMPLATES.about = compile('{{#link-to \'about.contact\' id=\'about-contact\' bubbles=boundFalseyThing}}About{{/link-to}}
{{outlet}}');
+ Ember.TEMPLATES['about/contact'] = compile('');
+
+ App.AboutController = Controller.extend({
+ boundFalseyThing: false
+ });
+
+ Router.map(function() {
+ this.route('about', function() {
+ this.route('contact');
+ });
+ });
+
+ var hidden = 0;
+
+ App.AboutRoute = Route.extend({
+ actions: {
+ hide() {
+ hidden++;
+ }
+ }
+ });
+
+ bootApplication();
+
+ run(function() {
+ router.handleURL('/about');
+ });
+
+ run(function() {
+ jQuery('#about-contact', '#qunit-fixture').click();
+ });
+
+ equal(jQuery('#contact', '#qunit-fixture').text(), 'Contact', 'precond - the link worked');
+
+ equal(hidden, 0, 'The link didn\'t bubble');
+});
+
QUnit.test('The {{link-to}} helper moves into the named route with context', function() {
Router.map(function(match) {
this.route('about');
@@ -686,6 +787,23 @@ QUnit.test('The {{link-to}} helper supports `target` attribute', function() {
equal(link.attr('target'), '_blank', 'The self-link contains `target` attribute');
});
+QUnit.test('The {{link-to}} helper supports `target` attribute specified as a bound param', function() {
+ Ember.TEMPLATES.index = compile('Home
{{#link-to \'index\' id=\'self-link\' target=boundLinkTarget}}Self{{/link-to}}');
+
+ App.IndexController = Controller.extend({
+ boundLinkTarget: '_blank'
+ });
+
+ bootApplication();
+
+ run(function() {
+ router.handleURL('/');
+ });
+
+ var link = jQuery('#self-link', '#qunit-fixture');
+ equal(link.attr('target'), '_blank', 'The self-link contains `target` attribute');
+});
+
QUnit.test('The {{link-to}} helper does not call preventDefault if `target` attribute is provided', function() {
Ember.TEMPLATES.index = compile('Home
{{#link-to \'index\' id=\'self-link\' target=\'_blank\'}}Self{{/link-to}}');
bootApplication();
@@ -1267,6 +1385,27 @@ QUnit.test('the {{link-to}} helper does not call preventDefault if `preventDefau
equal(event.isDefaultPrevented(), false, 'should not preventDefault');
});
+QUnit.test('the {{link-to}} helper does not call preventDefault if `preventDefault=boundFalseyThing` is passed as an option', function() {
+ Ember.TEMPLATES.index = compile('{{#link-to \'about\' id=\'about-link\' preventDefault=boundFalseyThing}}About{{/link-to}}');
+
+ App.IndexController = Controller.extend({
+ boundFalseyThing: false
+ });
+
+ Router.map(function() {
+ this.route('about');
+ });
+
+ bootApplication();
+
+ run(router, 'handleURL', '/');
+
+ var event = jQuery.Event('click');
+ jQuery('#about-link', '#qunit-fixture').trigger(event);
+
+ equal(event.isDefaultPrevented(), false, 'should not preventDefault');
+});
+
QUnit.test('the {{link-to}} helper does not throw an error if its route has exited', function() {
expect(0);
@@ -1523,3 +1662,52 @@ QUnit.test('Block-less {{link-to}} with only query-params updates when route cha
});
equal(jQuery('#the-link').attr('href'), '/about?bar=NAW&foo=456', 'link has right href');
});
+
+QUnit.test('The {{link-to}} helper can use dynamic params', function() {
+ Router.map(function(match) {
+ this.route('foo', { path: 'foo/:some/:thing' });
+ this.route('bar', { path: 'bar/:some/:thing/:else' });
+ });
+
+ let controller;
+ App.IndexController = Controller.extend({
+ init() {
+ this._super(...arguments);
+
+ controller = this;
+
+ this.dynamicLinkParams = [
+ 'foo',
+ 'one',
+ 'two'
+ ];
+ }
+ });
+
+ Ember.TEMPLATES.index = compile(`
+ Home
+
+ {{#link-to params=dynamicLinkParams id="dynamic-link"}}Dynamic{{/link-to}}
+ `);
+
+ bootApplication();
+
+ run(function() {
+ router.handleURL('/');
+ });
+
+ let link = jQuery('#dynamic-link', '#qunit-fixture');
+
+ equal(link.attr('href'), '/foo/one/two');
+
+ run(function() {
+ controller.set('dynamicLinkParams', [
+ 'bar',
+ 'one',
+ 'two',
+ 'three'
+ ]);
+ });
+
+ equal(link.attr('href'), '/bar/one/two/three');
+});