Skip to content

Proposal: Input as Observable #5689

Closed
Closed

Description

@lacolaco

Sorry, I'm not good at English.

@Input property values are provided by parent component. The changes come asynchronously.
And if Input property was changed in the child component (it has the property as own property) , its change detector never notice it.

Goal

  • Parent's input data and child's input property should be synchronized.
  • Developers should understand that input properties are changed asynchronously.

Proposal

@Component({ selector: "child" })
class Child {
  @Input("input") inputValue: Observable<T>;

  ngOnInit() {
    this.inputValue.map((value)=>...);
  }
}

@Component({
  template: `
  <child [input]="valueToChild"></child>
  `
})
class Parent {
  valueToChild: T;
}

Above code does not work. Currently, to receive input as Observable<T>, I must write it like below.

@Component({ selector: "child" })
class Child {
  @Input("input") inputValue: Observable<T>
}

@Component({
  template: `
  <child [input]="valueToChild"></child>
  `
})
class Parent {
  valueToChild: Observable<T> = new Observable<T>((observer)=>{
    ...
    observer.next(val);
  });
}

Example: http://plnkr.co/edit/BWziQygApOezTENdTVp1?p=preview

This works well, but it's not essential. Parent's input data is a simple data originally.

I think this proposal make us happy.

Thanks.

Activity

  1. robwormald commented on Dec 8, 2015

    @robwormald
    Contributor

    Hi @laco0416 - your English is fine, don't worry!

    I very much like this idea, and it's something we've discussed before. It also matches up nicely with #4062 (Observing view events) and #5467 (Observable child events from parents)

    It's important to remember that not everybody will want to use Observables (these people are missing out!), so we must provide options for both use cases, and so it's unlikely we'll make @Input() directly into an Observable. I do think that having something like @ObserveInput() might work, and we'll have a discussion after we ship beta about some of these more interesting features I think.

    In the meantime, here's a basic (and very experimental!!! do NOT do this for real) implementation of this idea. Is this conceptually what you were thinking? http://plnkr.co/edit/Nvyd9IPBZp9OE2widOcW?p=preview

  2. alexpods commented on Dec 8, 2015

    @alexpods

    I think it's a very bad idea to change input properties in a child component. Input properties should be "read-only". Your data should always flow from parent to child (and never in the reverse direction).

  3. robwormald commented on Dec 8, 2015

    @robwormald
    Contributor

    @alexpods i believe the idea here is exactly that - its listening to the change in input properties as an Observable, not emitting values upstream, which is absolutely fine as far as I'm concerned.

  4. lacolaco commented on Dec 8, 2015

    @lacolaco
    ContributorAuthor

    @robwormald

    your English is fine, don't worry!

    Thank you! I'm so relieved.

    Your @ObserveInput is what just I want!
    Also, @Input has no breaking changes. I think it is a very good solution.

  5. lacolaco commented on Dec 8, 2015

    @lacolaco
    ContributorAuthor

    @alexpods Me too at all.

    its listening to the change in input properties as an Observable, not emitting values upstream, which is absolutely fine as far as I'm concerned.

    I think in the same way as Rob.

  6. alexpods commented on Dec 8, 2015

    @alexpods

    @laco0416 Ooh, sorry for misunderstanding. The phrase "if Input property was changed in the child component" confused me.

  7. wmaurer commented on Jan 3, 2016

    @wmaurer

    I don't know if I should comment here or if I should open a new issue. Please let me know if I'm adding a request to the wrong place.

    I've been trying (but, until now, failing) to write a such a decorator, and then I stumbled upon @robwormald's plunkr, which works almost perfectly (but not quite).

    What got me excited by this approach was the fact that it is leveraging into the ngOnChanges lifecycle hook.
    What I would like to see is some way for all lifecycle hooks to be exposed as Observables, i.e. as onChanges$: Observable<{[key: string]: SimpleChange}>, onInit$: Observable<{}>, etc.

    Having all lifecycle hooks available as Observables will help me Rx all the things ;-)

  8. fxck commented on Feb 23, 2016

    @fxck

    Any updates on this?

  9. lacolaco commented on Feb 23, 2016

    @lacolaco
    ContributorAuthor

    AFAIK, No.
    @robwormald do you have any news?

  10. Guardiannw commented on Jul 15, 2016

    @Guardiannw

    I know this is old, but this would be great! @robwormald Any word on this?

  11. 280 remaining items

  12. lazarljubenovic commented on Jul 11, 2021

    @lazarljubenovic
    Contributor

    Over 99% of messages here have never been responded to by a team member. In fact, there are only five (5) replies by team members, the first one being 5 years after opening the issue: 2020-04-27, by mgechev; 2020-04-28, by mgechev; 2020-05-18, by mgechev; 2021-01-07, by mhevery; 2021-05-27, by JoostK, off-topic.

    After over 6 years, 250 upvotes and 300 comments, the issue gets closed with a generic comment of three and a half lines in size, by a person who has never before participated in the discussion.

    we pledge to respect everyone who contributes

    Apparently, respect doesn't include responding to the most popular issue with hundreds of ideas?

    We promise to extend courtesy and respect to everyone involved in this project

    Extend the courtesy and respect to everyone? Nah. Just close it with a stock reply after six years.

    If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at conduct@angular.io.

    But at least there's a way to combat disrespect. Thank you, Angular!

  13. mlc-mlapis commented on Jul 11, 2021

    @mlc-mlapis
    Contributor

    Probably everyone is anxiously awaiting what will follow as the next step. Currently, ~ 3/4 has been done, and ~ 1/4 is missing. Is it possible to think realistically about some magic idea that will connect the current state with some new all-embracing solution without massive breaking changes? After all, everything speaks in favor of the idea of finishing the remaining ~ 1/4 (like observable inputs, observable lifecycle hook streams, cold event template streams, ...), especially when many things it is not possible to move forward only by community efforts because changes are required at the internal level (compiler, ...). The current position of the Angular team does not make sense for this topic.

  14. insidewhy commented on Jul 12, 2021

    @insidewhy

    Turning inputs into Observables would more tightly couple Angular with RxJS, and we don't want to further couple with RxJS until we can discuss more broadly how we can utilize streamable / subscribeable APIs in a library agnostic way

    This request wasn't about turning inputs into Observables, so it would not have increased coupling between Angular and rxjs. All we were asking for was an option, one that would have reduced lots of boilerplate in our code and made us happier to use Angular. Given that the compiler only includes code one is actually using in the final build, it wouldn't have even had any effect on those who didn't want to use it.

    It would have been nice if at least we could write libraries to provide this feature. Yet all the libraries in this thread either have problems with boilerplate, subscription leaks, or stopped working due to Angular updates.

  15. zamzowd commented on Jul 12, 2021

    @zamzowd

    until we can discuss more broadly how we can utilize streamable / subscribeable APIs in a library agnostic way.

    Why is this discussion necessary? Why can't Angular just continue to use streamable / subscribable implementation of RxJS?

    If we do need this discussion, then can we get on that? This is just kicking the can down the road, not actually addressing the request raised in this issue.

  16. bryanrideshark commented on Jul 12, 2021

    @bryanrideshark

    You don't have to tightly couple it to rxjs to deliver this feature. You could make the construction of the Observables an injectable part of the framework, "ObservableFactory", just like how HttpClient is an injectable part of the framework. Folks could provide their own ObservableFactory, then they get to use core-js or whatever they want, and it would be over and done with.

    Also, if you're wanting to move away from a tight coupling on rxjs (which I don't get the motivation behind at all), you're going to need to implement some sort of "ObservableFactory" anyway.

    Please reconsider. If you don't, at least give us more rationale. There are so many ways to solve the reason you gave for closing it.

  17. pauldraper commented on Jul 12, 2021

    @pauldraper
    Contributor

    would more tightly couple Angular with RxJS

    @angular/common @angular/elements @angular/forms @angular/router: "Am I a joke to you?"

  18. jessicajaniuk commented on Jul 12, 2021

    @jessicajaniuk
    Contributor

    Thanks for all the discussion here. We just want to be clear that though we closed this issue, we are aware that it's a highly wanted feature. We aren't just ignoring it and do plan to address the feature need. We looked at this issue as a team and during our discussion, we decided that just implementing Observable for Inputs does have some drawbacks that we need to consider. We have no plans to divest in RxJS. We just were uncertain that in this case Observable was the best choice for streamable implementation as it has a lack of await support. Based on this feature request, we want to look at subscribable / "stream" based APIs in Angular holistically rather than just at this one issue in isolation, which is why the list of cross cutting issues related to this was posted. There will be a future feature proposal for streamables and component interaction that looks at this need as a whole. We will post a link to that feature request / issue on this thread once it's created.

  19. Airblader commented on Jul 12, 2021

    @Airblader
    Contributor

    @jessicajaniuk And do you have a (rough) timeline for that proposal?

    This is understandably frustrating for every user, because the crack in the door is kept open for a magical candy future where it will be addressed. That time hasn't come in the past six years(!), and without any meaningful statement, I doubt people will believe it'll happen in the next ten years either (I certainly don't).

    I also don't understand why the team chooses to do all of these things (assuming that they are in fact being done) behind Google curtains rather than transparently out in the open. If the team truly is discussing these plans behind the scenes, there are so many ways to do so while keeping the community informed (even if you keep us read-only).

  20. mlc-mlapis commented on Jul 12, 2021

    @mlc-mlapis
    Contributor

    There will be a future feature proposal for streamables and component interaction that looks at this need as a whole. We will post a link to that feature request / issue on this thread once it's created.

    @jessicajaniuk This sounds promising, and at the same time, it seems that the Angular team already has the basis of the proposed concept. If this is true, then the entire Angular community would very much welcome the publication of at least the basic building blocks of this concept and principled logic in the relatively foreseeable future. Is it possible to consider, say, about 4 - 6 weeks?

  21. abdulkareemnalband commented on Jul 13, 2021

    @abdulkareemnalband

    Angular Component already has dependency on rxjs because of @Output and EventEmitter

    I propose following solution without any breaking changes

    Input as observable could exposed as same as current @Output implementation

    The API could like

    @ObservableInput() name = something_which_returns_an_observer();
    

    And it could be used in template as any other input,

    <prefix-component [name]="value"></>
    

    Component Consumer does not need to worry about, whether component's input is defined using @ObservableInput() or @Input() , that is just internal implantation detail for said component

  22. abdulkareemnalband commented on Jul 13, 2021

    @abdulkareemnalband

    something_which_returns_an_observer could be Subject , ReplaySubject or BehaviorSubject

    If component author wants values as they arrive he can use

    @ObservableInput() name = new Subject();

    If component author wants values only when they are provided by template

    @ObservableInput() name = new ReplaySubject(1);

    If component author wants have a default value also then he can use

    @ObservableInput() name = new BehaviorSubject(default_value);
  23. pauldraper commented on Jul 13, 2021

    @pauldraper
    Contributor

    In the thread's spirit of half-assed third-party solutions to this common problem, I present my 30 line implementation: neo-observable-input.

    AFAIK unlike all other solutions proposed, this isn't a hack and it works with input typechecking in templates.

    Usage:

    import { Component, OnChanges } from "@angular/core";
    import { ObservableInputs } from "neo-observable-input";
    
    @Component({ template: "" })
    export class ExampleComponent implements OnChanges {
      private readonly inputs = new ObservableInputs();
    
      @Input()
      color: string;
      color$ = this.inputs.observe(() => this.color);
    
      @Input()
      count: number;
      count$ = this.inputs.observe(() => this.count);
    
      ngOnChanges() {
        this.inputs.onChanges();
      }
    }
  24. mgechev commented on Jul 13, 2021

    @mgechev
    Member

    Let me quickly follow up here as well. As we've discussed in the past, the community is very split when it comes to using less or more RxJS with Angular. The majority of folks on GitHub are advanced developers who feel comfortable with RxJS, which makes the feedback we get here a bit more skewed towards more RxJS. Additionally, we're mindful of the JavaScript we ship as part of the critical loading path of an application. Having RxJS as a hard dependency automatically adds extra KBs.

    That's why we want to explore the alternative of making RxJS optional for @angular/core in the future. There would be ways to achieve this with minimal breaking changes that we can automatically migrate because the framework's (@angular/core) runtime has a very lightweight dependency on RxJS.

    It's also essential for us to provide an ergonomic solution for people who want to embrace a more declarative and expressive development style with RxJS. We can do this without introducing additional coupling with RxJS. For example, we could look into the shape of the input and treat it differently if it is observable-like. This way, we can avoid a hard dependency on RxJS, and we'd also support more advanced use cases.

    That said, we have many solutions in mind, and this thread offers tens of other exciting options to explore. We closed the issue because of two main reasons:

    1. We want to ensure the API we implement is coherent with other parts of the framework. We don't want a one-off API, which works with observables and looks entirely out of place. Even though 30 line implementations could satisfy the basic requirements, we want to guarantee consistency with the rest of Angular, which will require planning, investigation, and more time.
    2. We want to be honest with what we can achieve in a specific timeframe and communicate that well with the community. It was not ideal in the first place that we kept the issue open for six years, posting sporadic comments. We unintentionally sent mixed messages and set unrealistic expectations with that communication pattern even though we were not close to implementing the feature.

    Since we want to set more realistic expectations in the future, we will share our plans for more ergonomic RxJS APIs when we prioritize that project. We'll make sure to follow up with an RFC and other resources that capture prior work and suggestions from the community to ensure we cover all the requirements of folks.

    Until we get there, I'd recommend using the community solutions that already exist and follow the roadmap for updates.

  25. angular-automatic-lock-bot commented on Aug 13, 2021

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

  26. locked and limited conversation to collaborators on Aug 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions