-
Notifications
You must be signed in to change notification settings - Fork 25.5k
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
Support for Dynamic Content Projection #8563
Comments
@tbosch looking for your input on how feasible this is. |
@mhevery thnx for opening this one. After reading through the proposal it looks like it would cover use-cases we've discussed yesterday plus solve some other ones I've bumped into previously. So it is all good from this perspective. There would be much more details to figure out and APIs to design, but IMO we can start working off your initial proposal. It would be great to have @tbosch input and see how we can move forward on this item. |
Technically this would work.
|
Under the cover, we would do the following:
Regarding how / when to update the property: Use a
|
Inserting the nodes requires a container that keeps track of them: Given the following example:
Here, the nodes of the nested For |
Given the above comments / analysis, I think we should do the following:
As the Also, we should change the semantics of
Finally, we should rename
|
Applied to the use case of wrapping projected elements:
I.e. |
@tbosch the latest proposal looks really great! I still need to go over all the use-cases I've got on my mind, but looks like a very promising start. One question for now, though: would I be able to get directives instances present on a given |
To get directives, you have to query for them as well:
We could change this to allow an array in
Or if you need the combination of
The
|
Can does this feature allow us to do processing like @Component({
selector: 'my-cmp',
template: `
<template [ngViewOutlet]="dynamicTemplate"></template>
`
})
class MyComponent {
dynamicTemplate = `<p>Hello</p>`;
} renderer HTML <my-cmp>
<p>Hello</p>
</my-cmp> |
@laco0416 sorry this has nothing to do with |
@pkozlowski-opensource @mhevery I changed my proposal above to use Also, I think we should only support this API for elements, not for text nodes (which would only be selected by |
@tbosch agreed. |
Talked with @mhevery a bit more how we can prevent breaking changes. We came up with the following:
|
@tbosch is this new plan a temporary measure just to avoid breaking changes? Or a proposal for the final solution? |
@pkozlowski-opensource the new plan is the actual solution. (since we don't see any benefits of adding breaking changes) |
@tbosch Is the |
I am unsure if I've read this issue correctly. Is there currently no other way to insert a component into another component (i.e. nested) programmatically? ViewContainerRef.createComponent() adds the new component instance as a sibling! This is strange behavior and not sure if it is intended. |
@patrickmichalina I've done a bunch of reading on this issue and I believe the behavior of ViewContainerRef.createComponent() is expected. Furthermore, I thought I had found a way to create the component as a child using the ComponentResolver and getting a ComponentFactory and calling create() on that factory. However, that does not seem to work as expected (see issue: 10523). |
I was thinking about post a new Feature Request Issue, but I would like that someone here check out that before. That is about ViewContainerRef.createEmbeddedView and @ContentChildren or @ViewChildren, the QueryList property don't detect when a child is added using createEmbeddedView. I think this feature covert my problem, am I right? |
Another excellent use case showing limitations of the current content projection + query system: #20810 (comment) |
My use case is, I'm creating a grid component with sensible defaults for header / filter and content layout. For the filter I need to use ContentChildren to get a list of Filters (in order to subscribe to their changes). Unfortunately ContentChildren doesn't find the FilterComponents when I use the default layout ng-template inside the grid component. It would be great to find a solution for this. |
@BenRacicot in your case step should be a structural directive that caries TemplateRef with it and inside stepper you would have ContentChildren and template outlet to instantiate correct template. This issue is more about dynamically moving things around instead of static select and project as. |
This comment has been minimized.
This comment has been minimized.
It would be nice if this solution could also make use of base class components as generic types. |
This comment has been minimized.
This comment has been minimized.
I Used ng-content with select on component. And on html ngFor directly with button to create buttons list
|
@ayslanjohnson but how do you reference those buttons in your component to allow a developer to use any component type they want inside a nested structure? When doing something like the following:
You are tied to only working with ButtonComponent classes and not their inheritance or even their abstract interface because you need to specify a component class in @ContentChildren (breaks Dependency Inversion principle). |
This is quite an old issue with no update, could someone with the knowledge comment on the state of this? It's been a big headache for me as I'm trying to dynamically create a MatTabGroup, but it uses @ContentChildren which I haven't been able to inject in any way that I've tried. I've tried using appendChild on the elements, using projectableNodes, setting the variable directly on the instance and none of them worked. |
I am looking to do something very similar to extend the functionality of some generic components I have. This functionality would be very useful for this. |
Use Case
<ng-content>
allows for static (compile time resolution) projection of content. There are cases where the projection needs to be controlled programmatically. A common example is when the parent component would like to wrap/decorate the child components during projection.Mental Model
The mental model would be that
<ng-content>
is for fast static projection, but for dynamic projection one would use a query to get a hold of the child components in the form ofViewRef
s which could then be inserted programmatically at any location in the tree.Possible Solution
ContentViewRef
extendsViewRef
@Content(selector)
Provides a way to select direct children content elements using CSS selectors. (This would be after directives such asngFor
would unroll the content, and it would be in the correct order.)ContentViewRef
s could then be reinserted to anyViewContainerRef
ngViewOutlet
(similar tongTemplateOutlet
).The text was updated successfully, but these errors were encountered: