-
Notifications
You must be signed in to change notification settings - Fork 26.9k
feat(NgComponentOutlet): add NgComponentOutlet directive #11235
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with commit is unrequired if you rebase on master
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, someone got me to it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove template and document the short syntax ?
<ng-container *ngComponentOutlet="..."></ng-container>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There no gain in using the short syntax since the element will never be used.
The only thing that get's rendered is the component.
I chose to enforce templateso this confusion can be avoided.
In the ng-content example the ng-content tag will be removed and the user won't understand why children won't project.
I had a discussion about this with @alexeagle @alxhub , he also supports that.
I believe this should be in NgTemplateOutlet as well.
However, if i'm missing something we can change this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
he also supports that
but IE doesn't :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am with @vicb
<ng-container *ngComponentOutlet="..."></ng-container>
is better because the long form than becomes
<ng-container *ngComponentOutlet="componentTypeExpression; injector: injExp; provider: proExp; projectable: proExp"></ng-container>
This means that all @Input need to be prefixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, giving it a bit more thought this is even better:
<ng-container *ngOutlet="component: componentTypeExpression; injector: injExp; provider: proExp; projectable: proExp"></ng-container>
182a0f0 to
5ccbf09
Compare
This commits adds a new NgComponentOutlet directive that can be used to dynamically create host views from a supplied component type/class. Closes angular#11168
5ccbf09 to
66342e6
Compare
|
@vicb Should I do something regarding the The TRIAGE_AND_LABELS.md says: Who's the 'assignee'? |
|
|
@vicb Good point on IE, will fix. |
|
Could you please rebase ? |
| @Directive({selector: 'template[ngComponentOutlet]'}) | ||
| export class NgComponentOutlet implements OnChanges { | ||
| @Input() ngComponentOutlet: Type<any>; | ||
| @Input() ngOutletInjector: Injector; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all input must start with the ngComponentOutlet prefix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vicb any thoughts on the issue comment below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do the rename above, then this name is fine.
|
@vicb almost done, one issue though... There is the This: Will error this: This: Won't error but won't trigger... I do expect this to happen as all directive bindings are set within the expression, the context here is the If this is a limitation I want to note that |
| } | ||
|
|
||
| const cmpRef = this._viewContainerRef.createComponent( | ||
| this._cmpFactoryResolver.resolveComponentFactory(this.ngComponentOutlet), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering why this doesn't cause issues when't it's called before ngAfterViewInit()?
Isn't ngOnChanges() called before ngAfterViewInit(), at least the first time?
You would obviously have run into issues, so I guess it's safe to assume it's working fine.
Any hint what I might misunderstand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What issues are you referring to?
this.ngComponentOutlet is checked in line 78, other null issues you see that i'm missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was sure that viewContainerRef.createComponent() can't be used before ngAfterViewInit()and was wondering why it seems to work for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test passes:
it('should work when a component was set before ngOnInit', async(() => {
let fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo');
}));For sure, ngOnChanges is called here before ngOnInit (thus ngAfterViewInit) and it triggers viewContainerRef.createComponent() since the component exists...
I was not aware of the limitation you mentioned, I experimented on this plunker it looks like this limitation does not exists at this point.
Am i'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shlomiassaf thanks. Seems I'll have to investigate and update my mental model ...
|
Gentle reminder on this topic, we are currently block by #12121. TL;DR:
Can you advise how to move forward? Should I ignore the lack of support for |
mhevery
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a good PR and should be merged after we get the names right.
| */ | ||
| @Directive({selector: 'template[ngComponentOutlet]'}) | ||
| export class NgComponentOutlet implements OnChanges { | ||
| @Input() ngComponentOutlet: Type<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename to ngOutletComponent
| @Directive({selector: 'template[ngComponentOutlet]'}) | ||
| export class NgComponentOutlet implements OnChanges { | ||
| @Input() ngComponentOutlet: Type<any>; | ||
| @Input() ngOutletInjector: Injector; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do the rename above, then this name is fine.
| * @experimental | ||
| */ | ||
| @Directive({selector: 'template[ngComponentOutlet]'}) | ||
| export class NgComponentOutlet implements OnChanges { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be renamed to NgOutlet since Component is a parameter of the outlet and should not be part of it.
|
What has become of this feature? |
|
Sorry guys, long business trip, will get it done hopefully this weekend. |
|
Thank you for doing this |
|
I have taken over this PR at #13383 |
Add NgComponentOutlet directive that can be used to dynamically create host views from a supplied component. Closes angular#11168 Takes over PR angular#11235
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Please check if the PR fulfills these requirements
What kind of change does this PR introduce? (check one with "x")
What is the current behavior? (You can also link to an open issue here)
See #11168
What is the new behavior?
See #11168
Does this PR introduce a breaking change? (check one with "x")
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
Other information:
This commits adds a new NgComponentOutlet directive that can be
used to dynamically create host views from a supplied component type/class.
Closes #11168
Closes #9599