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

feat: ng-decsendant; content projection between ancestors and descendant classes #13766

Open
chuckjaz opened this Issue Jan 4, 2017 · 18 comments

Comments

Projects
None yet
@chuckjaz
Member

chuckjaz commented Jan 4, 2017

I'm submitting a ... (check one with "x")

[x] feature request

Problem

Inspired by #13757

The template provided by an ancestor component is not useful to a descendant component since its content cannot be reference nor can it be used to build the descendant (even with #13764). This limits the usefulness of inheritance as a model for building components.

Proposal

Add a pseudo-element called ng-descendant that can be used analogously to ng-content except that the content is from the descendant class' template instead of instantiating template.

Descendant components are required to use an ng-extend elements that contains the content that is projected into the ancestor template. If the descendant does not use an ng-extend element as the root element of its template then its template will replace the ancestor template instead of extending it.

Example

@Component({
  template: `
    <h1><ng-descendant select=".header"></ng-descendant></h1>
    <ng-descendant select=".body"></ng-descendant>
    <div>
      <ng-descendant select=".footer"></ng-descendant>
    </div>`
})
class BaseClass {
}

@Component({
  template: `
    <ng-extend>
      <span class="header">My Component</span>
      <span class="body">Body of the component</span>
      <span class="footer">Footer of the component</span>
    </ng-extend>`  
})
class MyComponent extends BaseClass {
}

This would be interpreted as if MyComponent had been written as:

@Component({
    template: `
    <h1><span class="header">My Component</span></h1>
    <span class="body">Body of the component</span>
    <div>
       <span class="footer">Footer of the component</span>
    </div>`
})
class MyComponent extends BaseClass {
}
@asfernandes

This comment has been minimized.

asfernandes commented Jan 4, 2017

This is a proposal for the #13757 I just submitted.

@chuckjaz

This comment has been minimized.

Member

chuckjaz commented Jan 4, 2017

Exactly. I recast it to a concrete proposal. I was in the processes of commenting on yours to replace it with this more concrete proposal.

@chuckjaz

This comment has been minimized.

Member

chuckjaz commented Jan 4, 2017

I updated the content to directly reference your original request.

@vicb

This comment has been minimized.

Contributor

vicb commented Jan 4, 2017

@chuckjaz @asfernandes could you add concrete use cases ? Especially uses cases that could not be implemented with the current <ng-content>

@asfernandes

This comment has been minimized.

asfernandes commented Jan 4, 2017

Any case that inheritance makes more sense than composition. The example in the proposal is a valid one, define a base page with a generic layout.

Maybe could be implemented with another component and transclusion, but overall application design/implementation may make more sense to have a base class.

@chuckjaz

This comment has been minimized.

Member

chuckjaz commented Jan 4, 2017

<ng-descendant> is the inheritance analog to <ng-content> so it would be difficult (if not impossible) to come up with an example that would could not be accomplished with <ng-content> and composition. However, now that we are supporting inheritance as a mechanism to construct components the same use cases that justify <ng-content> for composition justify <ng-descendant> for inheritance.

As @asfernandes points out, there exist patterns that are more conveniently and efficiently expressed using inheritance. This feature would increase the reach of inheritance allowing it to be used when it is deemed more appropriate than composition.

@mlc-mlapis

This comment has been minimized.

mlc-mlapis commented Dec 12, 2017

@szanellato93 ... can you simply describe what is the problem in your example? I am not sure ...

@mlc-mlapis

This comment has been minimized.

mlc-mlapis commented Dec 12, 2017

@szanellato93 ... you are talking about HTML markup but there is no HTML at all finally in Angular app ... everything is compiled to JS ... so you can't access what doesn't exist.

@szanellato93

This comment has been minimized.

szanellato93 commented Dec 12, 2017

@mlc-mlapis i want that the Hello2 have Hello1 template with values of overrided properties of Hello2. See the name property, i override it but the Hello2 component still have the old name. The solution is change all override properties to Input and inject them.. but if there are a possibility to include the base component html and extend it, all work fine.

I'm reference the base component html when i don't need to change it and all work fine. I need a way to change it withoit creating an istance of it.

@mlc-mlapis

This comment has been minimized.

mlc-mlapis commented Dec 12, 2017

@szanellato93 ... without an instance it is just a class definition ... and its HTML template is present only by compiled JS functions ...

... so you are talking about transclusion that works together with inheritance ... when using extends?

@listepo

This comment has been minimized.

listepo commented Jan 19, 2018

@chuckjaz can we get this before Angular 6?

@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018

@sandrocsimas

This comment has been minimized.

sandrocsimas commented May 1, 2018

Currently I'm doing this way:
https://scotch.io/tutorials/angular-2-transclusion-using-ng-content
It's not inheritance but can solve some use cases. With inheritance is better because you can access the parent attributes easily.

@listepo-alterpost

This comment has been minimized.

listepo-alterpost commented May 23, 2018

@chuckjaz any news for Ivy Renderer?

@ErliSoares

This comment has been minimized.

ErliSoares commented May 25, 2018

This will help well.

@inspirassion

This comment has been minimized.

inspirassion commented Jul 3, 2018

This would be really great, it simplifies the design

@lambidu

This comment has been minimized.

lambidu commented Jul 26, 2018

Please, Angular Gods, give it to us!

@dalepo

This comment has been minimized.

dalepo commented Aug 24, 2018

I wanted to do my abstract CRUD with this :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment