Skip to content

Commit

Permalink
[BIGFIX release] Fix <LinkTo> with nested children
Browse files Browse the repository at this point in the history
During bubbling, `event.target` may point to a child element whereas
`event.currentTarget` always points to the element where the handler
was attached, which is what we want here.

Reported in a comment on #19546, though this may be a distinct issue
from the original report as it was reported as a default-cancelling
parent element interfering with the nested `<LinkTo>`, and this is
the other way around.

(cherry picked from commit 57907a4)
  • Loading branch information
chancancode committed Jun 10, 2021
1 parent fe32020 commit 6efbfba
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class LinkTo extends InternalComponent implements DeprecatingInternalComponent {
return;
}

let element = event.target;
let element = event.currentTarget;
assert('[BUG] must be an <a> element', element instanceof HTMLAnchorElement);

let isSelf = element.target === '' || element.target === '_self';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,47 @@ moduleFor(
);
}

async ['@test [GH#19546] it navigates into the named route when containing other elements'](
assert
) {
this.addTemplate(
'about',
`
<h3 class="about">About</h3>
<LinkTo @route='index' id='home-link'><span id='inside'>Home</span></LinkTo>
<LinkTo @route='about' id='self-link'>Self</LinkTo>
`
);

await this.visit('/about');

assert.equal(this.$('h3.about').length, 1, 'The about template was rendered');
assert.equal(
this.$('#self-link.active').length,
1,
'The self-link was rendered with active class'
);
assert.equal(
this.$('#home-link:not(.active)').length,
1,
'The other link was rendered without active class'
);

await this.click('#inside');

assert.equal(this.$('h3.home').length, 1, 'The home template was rendered');
assert.equal(
this.$('#self-link.active').length,
1,
'The self-link was rendered with active class'
);
assert.equal(
this.$('#about-link:not(.active)').length,
1,
'The other link was rendered without active class'
);
}

async [`@test [DEPRECATED] it doesn't add an href when the tagName isn't 'a'`](assert) {
this.addTemplate(
'index',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,47 @@ moduleFor(
);
}

async ['@test [GH#19546] it navigates into the named route when containing other elements'](
assert
) {
this.addTemplate(
'about',
`
<h3 class="about">About</h3>
<div id="home-link">{{#link-to route='index'}}<span id='inside'>Home</span>{{/link-to}}</div>
<div id="self-link">{{#link-to route='about'}}Self{{/link-to}}</div>
`
);

await this.visit('/about');

assert.equal(this.$('h3.about').length, 1, 'The about template was rendered');
assert.equal(
this.$('#self-link > a.active').length,
1,
'The self-link was rendered with active class'
);
assert.equal(
this.$('#home-link > a:not(.active)').length,
1,
'The other link was rendered without active class'
);

await this.click('#inside');

assert.equal(this.$('h3.home').length, 1, 'The home template was rendered');
assert.equal(
this.$('#self-link > a.active').length,
1,
'The self-link was rendered with active class'
);
assert.equal(
this.$('#about-link > a:not(.active)').length,
1,
'The other link was rendered without active class'
);
}

async [`@test [DEPRECATED] it doesn't add an href when the tagName isn't 'a'`](assert) {
this.addTemplate(
'index',
Expand Down

0 comments on commit 6efbfba

Please sign in to comment.