Skip to content

Conversation

@shlomiassaf
Copy link
Contributor

@shlomiassaf shlomiassaf commented Sep 1, 2016

Please check if the PR fulfills these requirements

What kind of change does this PR introduce? (check one with "x")

[ ] Bugfix
[x] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Other... Please describe:

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")

[ ] Yes
[x] No

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

Copy link
Contributor

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

Copy link
Contributor Author

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 :)

@vicb vicb added this to the 2.0.1 milestone Sep 1, 2016
Copy link
Contributor

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>

Copy link
Contributor Author

@shlomiassaf shlomiassaf Sep 1, 2016

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.

Copy link
Contributor

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 :)

Copy link
Contributor

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.

Copy link
Contributor

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>

@vicb vicb added the action: review The PR is still awaiting reviews from at least one requested reviewer label Sep 1, 2016
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
@vicb vicb 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 Sep 3, 2016
@shlomiassaf
Copy link
Contributor Author

shlomiassaf commented Sep 4, 2016

@vicb Should I do something regarding the pr_action: cleanup?

The TRIAGE_AND_LABELS.md says:

pr_action: cleanup -- more work is needed from the current assignee.

Who's the 'assignee'?

@vicb
Copy link
Contributor

vicb commented Sep 4, 2016

  • we won't merge new features into master for for next few weeks only bug fixes,
  • you still have not address my comment for IE not supporting template

@shlomiassaf
Copy link
Contributor Author

@vicb Good point on IE, will fix.

@vicb
Copy link
Contributor

vicb commented Sep 16, 2016

Could you please rebase ?

@Directive({selector: 'template[ngComponentOutlet]'})
export class NgComponentOutlet implements OnChanges {
@Input() ngComponentOutlet: Type<any>;
@Input() ngOutletInjector: Injector;
Copy link
Contributor

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

Copy link
Contributor Author

@shlomiassaf shlomiassaf Sep 22, 2016

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?

Copy link
Contributor

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.

@shlomiassaf
Copy link
Contributor Author

shlomiassaf commented Sep 17, 2016

@vicb almost done, one issue though...
I couldn't pass a test where using the sugared syntax * I can use an @Output on the structural directive.

There is the ngComponentOutletCreated @Output which I couldn't get working on the tests, I couldn't find any reference in the angular code either....

This:

`<div *ngComponentOutlet="currentComponent; providers:providers; created: onOutletCreate($event)"></div>`;

Will error this:

        Can't bind to 'ngComponentOutletCreated' since it isn't a known property of 'div'. ("<div [ERROR ->]*ngComponentOutlet="currentComponent; providers:providers; created: onOutletCreate($event)"

This:
<div *ngComponentOutlet="currentComponent; providers:providers" (ngComponentOutletCreated)="onOutletCreate($event)"></div>;

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 div not the directive.

If this is a limitation I want to note that * syntax also does not allow exportAs so it wont be possible to get the directive as a local template var and subscribe.
You could, I assume, use @Self or @Host to get the directive instance and subscribe.

}

const cmpRef = this._viewContainerRef.createComponent(
this._cmpFactoryResolver.resolveComponentFactory(this.ngComponentOutlet),
Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zoechi

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?

Copy link
Contributor

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 ...

@vicb vicb modified the milestones: 2.0.1, 2.0.2, 2.1.0 Sep 29, 2016
@vsavkin vsavkin added the area: common Issues related to APIs in the @angular/common package label Oct 4, 2016
@shlomiassaf
Copy link
Contributor Author

@vicb @vsavkin I need some help with the unsupported feature in angular.
Sugared directives does no support @Output
Should I just ignore that?

@mhevery
Copy link
Contributor

mhevery commented Oct 20, 2016

Ping @vicb / @vsavkin, can you help with reviewing this PR?

@shlomiassaf
Copy link
Contributor Author

@mhevery / @vicb / @vsavkin,

Gentle reminder on this topic, we are currently block by #12121.

TL;DR:

  • To support IE we need to support sugar syntax (no template tag)
  • Sugar syntax does not support @output registration (the blocker...)

Can you advise how to move forward?

Should I ignore the lack of support for @Output when using sugar syntax?

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.

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>;
Copy link
Contributor

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;
Copy link
Contributor

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 {
Copy link
Contributor

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.

@shlomiassaf
Copy link
Contributor Author

@mhevery 👍

I already have a fixed version for sugar syntax but I do have blockers since @Output is not supported.

I will rename the component and post the PR.
Using sugar syntax will be fine but the output wont fire... until #12121 is fixed

@luchillo17
Copy link

What has become of this feature?

@shlomiassaf
Copy link
Contributor Author

Sorry guys, long business trip, will get it done hopefully this weekend.

@dehru
Copy link

dehru commented Dec 10, 2016

Thank you for doing this

@mhevery
Copy link
Contributor

mhevery commented Dec 11, 2016

I have taken over this PR at #13383

@mhevery mhevery closed this Dec 11, 2016
mhevery pushed a commit to mhevery/angular that referenced this pull request Jan 7, 2017
Add NgComponentOutlet directive that can be used to dynamically create
host views from a supplied component.

Closes angular#11168
Takes over PR angular#11235
matsko pushed a commit that referenced this pull request Jan 9, 2017
Add NgComponentOutlet directive that can be used to dynamically create
host views from a supplied component.

Closes #11168
Takes over PR #11235
@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 Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews action: review The PR is still awaiting reviews from at least one requested reviewer area: common Issues related to APIs in the @angular/common package cla: yes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] NgComponentOutlet Proposal: Declarative Dynamic Components

8 participants