question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: Support declarative binding from View events to Observables

See original GitHub issue

Not sure this is a good idea, or even possible, but thought I’d throw it out there.

In vanilla Rx, if I wanted to listen to a DOM event to do a typeahead or something I’d do something like:

//get DOM element
const input = document.getElementById('myInput');
//observable of click events
const inputs$ = Rx.Observable.fromEvent(input, 'keyup');
//map changes to requests
const responses$ = inputs$.flatMap(ev => myHttpService.get(ev.target.value)); 
//subscribe to responses
responses$.subscribe(json => console.log(json));

In current ng2, if I wanted to do the equivalent, I’d do something like:

@Component({
  selector: 'my-component'
})
@View({
  template: `
     <div [ng-form-model]="myForm">
       <input type="text" ng-control="query">
    </div>
    <ul>
     <li *ng-for="#result of results | async">{{result.text}}</li>
   </ul>
`
})
class MyComponent {
  constructor(public http: Http, fb: FormBuilder){
    //create form group
    this.myForm = fb.group({
      query: ""
    });
    //subscribe to value changes, map to responses, bind to view w/ pipe
    this.results = this.myForm.controls.query.valueChanges
      .toRx()
      .flatMap(query => this.http.get(`/foos?q=${query}`)
      .map(res => res.json());
  }
}

This all works great (or will, once Rx stuff settles).

However, if I wanted to do the same sort of thing from an arbitrary event (unrelated to forms, like a mousedrag or button click or whatever), there’s not a good way (I can see) to get an Observable from a DOM event, so you have to do something like:

<button (click)="makeRequest($event)">Make Request</button>
//snip
class MyComponent {
  makeRequest($event){
    this.http.get($event.target.url)
      .map(res => res.json())
      .subscribe(results => this.results = results);
  }
}

which isn’t nearly as clean.

Proposed idea would be to provide a way to delegate / bind an arbitrary DOM event to a Subject/Observable, so that it could be easily subscribed to and handled reactively.

Something like (totally made up syntax here, point being we’re binding the click event to the Subject):

Edit: see https://github.com/angular/angular/issues/4062#issuecomment-231615401 for current proposal

<button [(click)]="clicks$">make request</button>
class MyComponent {
  clicks$ = new Rx.Subject();
  constructor(){
    this.results = this.clicks$
      .flatMap(ev => http.get('someurl.json'))
      .map(res => res.json())
  }
}

I saw https://github.com/angular/angular/pull/3992, but I believe this is for emitting events “out” from the component, whereas this idea is more for usage within a component.

Thoughts?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:43
  • Comments:62 (35 by maintainers)

github_iconTop GitHub Comments

21reactions
mheverycommented, Mar 11, 2016

Just a little update. We think this use case is important and it should be included in the core of Angular. For now the focus is on Final, and this is a feature which can be added after final release, so don’t expect much progress until after final release.

15reactions
PatrickJScommented, Jan 14, 2018

update: the plunker angular version needs to be updated to latest angular for it to work again

I want access to child outputs in the constructor so can have full access to rxjs that way we can unlock the reactive potential out of Angular 2. Here’s an example using the initial plunker prototype

screen shot 2016-07-11 at 1 53 11 am https://plnkr.co/edit/8aN2hK?p=preview I was able to get it working on the prototype in a similar hacky way and using `EventEmitter (aka Subject)` as a proxy. With this, we're able to create cycles at any level in the component tree. Now I just want to pass the child Observables up the tree which I guess you could support with by combining `@Output` and `@ObserveChild` as I have in the example and also Observable inputs.

All I want is for everything in constructor to be Observables so we can wire everything up. This includes Input/ViewChild/ViewChildren/ContentChild/ContentChildren (pending router Data/Resolved/Params) which would allow for Angular 2 to become powerful with advanced reactive configs. If anyone wants to deal with sync values they can use the correct lifecycle hooks

@ObserveInput @ObserveViewChild @ObserveViewChildren @ObserveContentChild @ObserveContentChildren /
I got all of these working in a prototype via AngularClass/angular2-observe-decorators

github-tipe-logo

Read more comments on GitHub >

github_iconTop Results From Across the Web

Making HostBinding work with Observables - Angular inDepth
Host binding to ARIA attributes, title or alt for images is currently problematic. Changing host class or style. Observable service can control ...
Read more >
Observables compared to other techniques - Angular
Observables are often compared to promises. Here are some key differences: Observables are declarative; computation does not start until subscription. Promises ...
Read more >
Observables - Knockout.js
Observables. Knockout is built around three core features: Observables and dependency tracking; Declarative bindings; Templating. On this page, you'll learn ...
Read more >
How Knockout JS Declarative Binding internally works
An observable is a function, and invoking it without arguments gets its current value. Knockout will "magically" add those parentheses if it ...
Read more >
[DataBinding] Remove observable factories from data binding ...
We abandoned this design because we felt it constrained us from evolving the API. The set of Observables created by the standard factories...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found