Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): not inserting ViewContainerRef nodes when inside root of a component #39599

Closed
wants to merge 2 commits into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Nov 7, 2020

When a ViewContainerRef is injected, we dynamically create a comment node next to the host so that it can be used as an anchor point for inserting views. The comment node is inserted through the appendChild helper from node_manipulation.ts in most cases.

The problem with using appendChild here is that it has some extra logic which doesn't return a parent RNode if an element is at the root of a component. I think that this is a performance optimization which is used to avoid inserting an element in one place in the DOM and then moving it a bit later when it is projected. This can break down in some cases when creating a ViewContainerRef for a non-component node at the root of another component like the following:

<root>
  <div #viewContainerRef></div>
</root>

In this case the #viewContainerRef node is at the root of a component so we intentionally don't insert it, but since its anchor element was created manually, it'll never be projected. This will prevent any views added through the ViewContainerRef from being inserted into the DOM.

These changes resolve the issue by not going through appendChild at all when creating a comment node for ViewContainerRef. This should work identically since appendChild doesn't really do anything with the T structures anyway, it only uses them to reach the relevant DOM nodes.

Fixes #39556.

@google-cla google-cla bot added the cla: yes label Nov 7, 2020
@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime type: bug/fix labels Nov 7, 2020
@ngbot ngbot bot modified the milestone: needsTriage Nov 7, 2020
@crisbeto crisbeto marked this pull request as ready for review November 7, 2020 15:47
const tNode = tData[parentTNode.index] as TNode;
const encapsulation = (tData[tNode.directiveStart] as ComponentDef<any>).encapsulation;
const encapsulation =
(tView.data[parentTNode.directiveStart] as ComponentDef<unknown>).encapsulation;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes aren't required for the fix, I just noticed that the tNode and parentTNode are always the same here.

Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change LGTM, thanks @crisbeto 👍

I've also added @mhevery as a reviewer, I think his input might also be very helpful.

Copy link
Contributor

@mhevery mhevery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but please take care of @AndrewKushnir 's comments

@mhevery mhevery added the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Nov 10, 2020
… component

When a `ViewContainerRef` is injected, we dynamically create a comment node next to the host
so that it can be used as an anchor point for inserting views. The comment node is inserted
through the `appendChild` helper from `node_manipulation.ts` in most cases.

The problem with using `appendChild` here is that it has some extra logic which doesn't return
a parent `RNode` if an element is at the root of a component. I __think__ that this is a performance
optimization which is used to avoid inserting an element in one place in the DOM and then
moving it a bit later when it is projected. This can break down in some cases when creating
a `ViewContainerRef` for a non-component node at the root of another component like the following:

```
<root>
  <div #viewContainerRef></div>
</root>
```

In this case the `#viewContainerRef` node is at the root of a component so we intentionally don't
insert it, but since its anchor element was created manually, it'll never be projected. This will
prevent any views added through the `ViewContainerRef` from being inserted into the DOM.

These changes resolve the issue by not going through `appendChild` at all when creating a comment
node for `ViewContainerRef`. This should work identically since `appendChild` doesn't really do
anything with the T structures anyway, it only uses them to reach the relevant DOM nodes.

Fixes angular#39556.
@crisbeto crisbeto removed the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Nov 10, 2020
@crisbeto
Copy link
Member Author

@AndrewKushnir the feedback has been addressed.

@petebacondarwin petebacondarwin added the action: presubmit The PR is in need of a google3 presubmit label Nov 10, 2020
@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Nov 10, 2020
@AndrewKushnir
Copy link
Contributor

Presubmit.

@AndrewKushnir AndrewKushnir removed the action: presubmit The PR is in need of a google3 presubmit label Nov 11, 2020
@AndrewKushnir
Copy link
Contributor

@crisbeto FYI presubmit is successful for the changes in this PR. The missing piece is the "target" label, could you please set one when you get a chance? Thank you.

@crisbeto crisbeto added the target: patch This PR is targeted for the next patch release label Nov 11, 2020
@atscott atscott closed this in b015d3e Nov 12, 2020
atscott pushed a commit that referenced this pull request Nov 12, 2020
… component (#39599)

When a `ViewContainerRef` is injected, we dynamically create a comment node next to the host
so that it can be used as an anchor point for inserting views. The comment node is inserted
through the `appendChild` helper from `node_manipulation.ts` in most cases.

The problem with using `appendChild` here is that it has some extra logic which doesn't return
a parent `RNode` if an element is at the root of a component. I __think__ that this is a performance
optimization which is used to avoid inserting an element in one place in the DOM and then
moving it a bit later when it is projected. This can break down in some cases when creating
a `ViewContainerRef` for a non-component node at the root of another component like the following:

```
<root>
  <div #viewContainerRef></div>
</root>
```

In this case the `#viewContainerRef` node is at the root of a component so we intentionally don't
insert it, but since its anchor element was created manually, it'll never be projected. This will
prevent any views added through the `ViewContainerRef` from being inserted into the DOM.

These changes resolve the issue by not going through `appendChild` at all when creating a comment
node for `ViewContainerRef`. This should work identically since `appendChild` doesn't really do
anything with the T structures anyway, it only uses them to reach the relevant DOM nodes.

Fixes #39556.

PR Close #39599
basherr pushed a commit to basherr/angular that referenced this pull request Nov 14, 2020
… component (angular#39599)

When a `ViewContainerRef` is injected, we dynamically create a comment node next to the host
so that it can be used as an anchor point for inserting views. The comment node is inserted
through the `appendChild` helper from `node_manipulation.ts` in most cases.

The problem with using `appendChild` here is that it has some extra logic which doesn't return
a parent `RNode` if an element is at the root of a component. I __think__ that this is a performance
optimization which is used to avoid inserting an element in one place in the DOM and then
moving it a bit later when it is projected. This can break down in some cases when creating
a `ViewContainerRef` for a non-component node at the root of another component like the following:

```
<root>
  <div #viewContainerRef></div>
</root>
```

In this case the `#viewContainerRef` node is at the root of a component so we intentionally don't
insert it, but since its anchor element was created manually, it'll never be projected. This will
prevent any views added through the `ViewContainerRef` from being inserted into the DOM.

These changes resolve the issue by not going through `appendChild` at all when creating a comment
node for `ViewContainerRef`. This should work identically since `appendChild` doesn't really do
anything with the T structures anyway, it only uses them to reach the relevant DOM nodes.

Fixes angular#39556.

PR Close angular#39599
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Dec 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime cla: yes merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: patch This PR is targeted for the next patch release type: bug/fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dynamic Component not insert into shadowDOM
4 participants