Skip to content
This repository has been archived by the owner on Sep 16, 2022. It is now read-only.

Support component inheritance #231

Closed
f-mon opened this issue Dec 17, 2016 · 17 comments
Closed

Support component inheritance #231

f-mon opened this issue Dec 17, 2016 · 17 comments

Comments

@f-mon
Copy link

f-mon commented Dec 17, 2016

At current time Angular Dart doesn't support component hineritance of @component and @input and other metadata. This very important feature has been added in angular 2.3.0, are there any plan to support this in angular dart?

@daniel-v
Copy link

daniel-v commented Feb 6, 2017

Might I ask what is this blocked by? This would be a neat feature.

@TedSander
Copy link
Contributor

We need to use resolved ASTs for codegen to enable this. The blocker is currently being worked on.

@matanlurey
Copy link
Contributor

@f-mon @daniel-v This will be in 3.0.0, though I can't say if it will be immediate or not.

@matanlurey matanlurey added this to the V3 Final milestone Feb 7, 2017
@matanlurey matanlurey changed the title Support component hineritance Support component inheritance Mar 29, 2017
@matanlurey
Copy link
Contributor

matanlurey commented Mar 29, 2017

Pushed to 4.0. We have all the work ready to support this, but are still testing this doesn't cause regressions or build performance issues so we don't want to block 3.0. Should be coming soon.

@matanlurey matanlurey modified the milestones: Post-V3, V3 Final Mar 29, 2017
@matanlurey
Copy link
Contributor

This is now planned for the 4.0 release.

@matanlurey
Copy link
Contributor

If anyone would like to start an RFC on how this should work (or refer to TypeScript's implementation) that would be awesome. There is a chance this might slip from 4.0 but I'd personally love to see it.

@Lisenish
Copy link

Lisenish commented Jun 6, 2017

I would like to participate in this.
Also, I want to note it would be great to implement @component annotation inheritance not only @input like on TS Angular, as we can see in this issue angular/angular#7968 this is a highly requested feature but looks like guys from TS version doesn't agree with the community proposal. So it can be the small killer feature of AngularDart vs AngularTS =).

@leonsenft
Copy link
Contributor

We plan to support inheritance for all property annotations in 4.0.0.

  • @ContentChild
  • @ContentChildren
  • @HostBinding
  • @HostListener
  • @Input
  • @Output
  • @ViewChild
  • @ViewChildren

Derived components will inherit their ancestor's property annotations, and may choose to override their implementations. If a derived component re-declares a named annotation on a different property, we'll treat this similarly to how duplicate annotations in a component currently behave.

We won't be adding support for inheritance of class annotations yet.

  • @Component
  • @Directive
  • @Pipe

@leonsenft
Copy link
Contributor

leonsenft commented Jun 19, 2017

Thank you for your support and interest @Lisenish. If you have any feedback on our current plans I'd be glad to hear it. If you feel strongly about inheritable class annotations, please feel to provide some details on how you'd like that to work.

There's no one clear way to inherit class annotations. Since we haven't seen much demand for it yet, there's not much sense in committing to one arbitrary solution.

@zoechi
Copy link

zoechi commented Jun 20, 2017

We won't be adding support for inheritance of class annotations yet.

I assume this just means annotations of sub and superclass aren't "merged", but need to repeated with all parameters on the subclass, right?

@matanlurey
Copy link
Contributor

It means the top-level @Component|Directive|Pipe is not inherited, only individual annotations on fields. For example, this would be inherited:

class AComp {
  @Input()
  String a;
}

// Still has an @Input() for a.
class BComp extends AComp {}

@Lisenish
Copy link

@leonsenft Good to hear, thanks!
About annotation inheritance, this is mostly about reusing parent component template and providers. I have the case where I need child component that differs from the parent only in a selector and some business logic. Now I have to duplicate component template in child component
I understand that class annotation inheritance isn't very transparent and why you are trying to avoid this feature. But maybe we can figure out how to deal with this duplication?

@leonsenft
Copy link
Contributor

@Lisenish
If your desire is to inherit the template and providers as-is, you can already do so without duplication by using templateUrl and a predefined list of providers.

const baseProviders = const [...];

@Component(
  selector: 'base',
  templateUrl: 'base_component.html',
  providers: baseProviders,
)
class BaseComponent {
  ...
}

@Component(
  selector: 'derived',
  templateUrl: 'base_component.html', // reuse supertype template URL
  providers: baseProviders, // reuse supertype providers
)
class DerivedComponent extends BaseComponent {
  ...
}

Yes, you still have to specify the templateUrl and providers argument in the component annotation, but this is a tiny, constant amount of work per component.

My concern with your proposed solution is it's all or nothing. You either inherit the base metadata as-is, or replace it entirely. A solution where the derived component can interact in some way with its inherited metadata is much more compelling.

Notice that all of the metadata we're initially supporting annotates a component method or property. Methods and property accessors can reference their inherited implementations via super and extend on them if desired.

No parallel to this concept exists for annotation arguments. For example, a @Component annotation on a derived component could not reference the template specified in the @Component annotation of the base component.

Just to be clear, we're not ruling out any particular implementation yet. We want to be sure that if and when we implement this, we get it right.

I'd like to reiterate my earlier point that we just haven't seen much of a demand for inheritable templates/styles/providers and how particular implementations could solve problems in ways the framework currently struggles to. If you have a compelling example, we'd be happy to see a new issue with a detailed proposal.

@zoechi
Copy link

zoechi commented Jun 27, 2017

Polymer dropped template inheritance before 1.0 where the subclass can extend the template, because it was too complicated.

@Lisenish
Copy link

@leonsenft Thanks for the detailed answer and clarification!
Yeah, I was thinking about that solution that you proposed too after I had wrote comment.
Actually, I changed my mind I would agree with you, looks like it's pretty difficult to implement and say how it should work while profit is minimal.
For now, we are waiting Input and View/ContentChild inheritance, this is must have for sure!

alorenzen pushed a commit that referenced this issue Jun 28, 2017
Components now inherit the following metadata from their ancestor components

* Host bindings
* Host listeners
* Inputs
* Outputs
* Queries
* View queries

Inheritance prohibits changing the binding names of inherited inputs and
outputs. This ensures derived components preserve their inherited API, allowing
seamless substitution of component subtypes.

A consequence of this restriction, is that inheritance doesn't work well with a
common directive pattern. It's typical for directives that rely on a primary
input to use the same attribute for the input binding name and directive
selector. If another directive were to inherit from such a directive,
maintaining this pattern would require changing the inherited input binding
name to match the derived directive's selector. As a result, inheritance of
directives isn't supported yet.

Progress towards #231.

PiperOrigin-RevId: 160446534
alorenzen pushed a commit that referenced this issue Jun 29, 2017
alorenzen pushed a commit that referenced this issue Jun 29, 2017
Components now inherit the following metadata from their ancestor components

* Host bindings
* Host listeners
* Inputs
* Outputs
* Queries
* View queries

Inheritance prohibits changing the binding names of inherited inputs and
outputs. This ensures derived components preserve their inherited API, allowing
seamless substitution of component subtypes.

A consequence of this restriction, is that inheritance doesn't work well with a
common directive pattern. It's typical for directives that rely on a primary
input to use the same attribute for the input binding name and directive
selector. If another directive were to inherit from such a directive,
maintaining this pattern would require changing the inherited input binding
name to match the derived directive's selector. As a result, inheritance of
directives isn't supported yet.

Progress towards #231.

PiperOrigin-RevId: 160446534
alorenzen pushed a commit that referenced this issue Jun 29, 2017
@matanlurey
Copy link
Contributor

@leonsenft your latest commits landed into master - do you want to mark this done?

@leonsenft
Copy link
Contributor

@matanlurey Not yet; only very limited support is landed. Currently components only support inheritance from ancestor components and directives. I have a pending change which extends inheritance to all ancestors, so you can annotate regular classes with metadata.

alorenzen pushed a commit that referenced this issue Jul 13, 2017
…ering

* If an inherited @input was declared on a field, a derived component could
  override the binding name on a setter.
* If an inherited @input was declared on a setter, a derived component could
  declare a new binding name on a field which would silently fail.

Progress on #231.

PiperOrigin-RevId: 161823863
alorenzen pushed a commit that referenced this issue Jul 14, 2017
…ering

* If an inherited @input was declared on a field, a derived component could
  override the binding name on a setter.
* If an inherited @input was declared on a setter, a derived component could
  declare a new binding name on a field which would silently fail.

Progress on #231.

PiperOrigin-RevId: 161823863
alorenzen pushed a commit that referenced this issue Jul 18, 2017
Closes #231.

PiperOrigin-RevId: 162000574
alorenzen pushed a commit that referenced this issue Jul 18, 2017
…g names

Polishing #231.

PiperOrigin-RevId: 162369805
matanlurey pushed a commit that referenced this issue Jul 19, 2017
…g names

Polishing #231.

PiperOrigin-RevId: 162369805
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants