Skip to content

Interface-based lifecycle methods #2120

Closed

Description

@yjbanov

We currently declare lifecycle callback methods in annotations:

@Component(
  lifecycle: const [onChange]
)
class MyComponent {
  void onChnage() { ... }
}

This is not idiomatic in Dart and error-prone in both Dart and TypeScript. Note that in the example above I misspelled the method. Also note that the signature of the method is wrong. There's no warning from the analyzer about these mistakes.

Proposal

This is more idiomatic Dart:

@Component()
class MyComponent implements OnChange {
  @override
  void onChange(_) { ... }
}

With this you get much better feedback from tools.

Because @Component is shared between Dart and JS we will extract "lifecycle" property into its own annotation @Lifecycle for use with JS:

@Component({...})
@Lifecycle({[onChange]})
class MyComponent {
  onChange():void { ... }
}

The reason we need to keep @Lifecycle is because TypeScript does not reify interfaces, so there is no way to reflectively tell if a class implements an interface.

Components intended to transpile to both languages (such as our own material components) would simply use both:

@Component({...})
@Lifecycle({[onChange]})
class MyComponent implements OnChange {
  onChange(_):void { ... }
}

Dart would ignore @Lifecycle and JS would ignore implements OnChange.

Related issue: #1943

Activity

  1. changed the title [-]Dart: interface-based lifecycle methods[/-] [+]Interface-based lifecycle methods[/+] on May 22, 2015
  2. yjbanov commented on May 22, 2015

    @yjbanov
    ContributorAuthor

    Assigning to @vsavkin to validate the idea. We can reassign to anyone willing to implement once we agree on it.

  3. vicb commented on May 26, 2015

    @vicb
    Contributor

    Is OnChange a good name ? (not very descriptive, easy to mix with onChange).

    I am not really keen on

    @Component({...})
    @Lifecycle({[onChange]})
    class MyComponent implements OnChange {
      onChange(_):void { ... }
    }

    as an alternative, we could rename onChange to something more specific and use a structural type check for JS:

    @Component({...})
    class MyComponent implements OnChange {
      onBindingsChanged(_):void { ... }
    }

    the implements OnChange would be optional in JS but documented as a best-practice.

    Also I think we do not inherit annotations for now ? If this is true, the interface based behavior would be different as of today.

  4. JavascriptMick commented on May 26, 2015

    @JavascriptMick

    what about

    @Component()
    class MyComponent implements Changeable, Destroyable {
      @override
      void onChange(_) { ... }
    
    @override
      void onDestroy(_) { ... }
    }
    
  5. vicb commented on May 26, 2015

    @vicb
    Contributor

    MyComponent could change even if it does not implements Changeable.

  6. tbosch commented on May 26, 2015

    @tbosch
    Contributor

    +1 for using structural type checks in JS land as well (e.g. via checking the prototype), so we keep the same syntax in both, Dart and JS (i.e. don't need @Lifecycle annotation at all)

  7. kegluneq commented on May 29, 2015

    @kegluneq

    I like this generally, but for the transformer this introduces some nasty edge cases.

    To avoid the slowdown seen with the AngularDart (#1) transformer, we do not have a fully resolved AST or global information at transform time. With some exceptions, when operating on a file we only have the information available in that file. As an example, if we have:

    a.dart:

    class A implements OnChange {}
    

    b.dart

    class B extends A {}
    

    We won't know that B implements OnChange.

    @vsavkin and I talked about this and settled on requiring OnChange to be explicitly specified even if it is already inherited.

    Any objections?

  8. vicb commented on May 29, 2015

    @vicb
    Contributor

    @kegluneq would you mind cross posting on #2220, this issue is closed.

    I understand the why but I don't really like the solution. If you extend some Directives, you'll have to check its signature before doing so, far from ideal - not to mention issues when the base class signature changes.

  9. angular-automatic-lock-bot commented on Sep 6, 2019

    @angular-automatic-lock-bot

    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.

  10. locked and limited conversation to collaborators on Sep 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions