Search code examples
angularangularjs-directivedartangular-dart

angulardart: how StreamController works in the following example?


I am reading the tutorial.

Example 1:

lib/src/hero_search_component.dart

class HeroSearchComponent implements OnInit {
  HeroSearchService _heroSearchService;
  Router _router;
  Stream<List<Hero>> heroes;
  StreamController<String> _searchTerms =
      new StreamController<String>.broadcast();
  HeroSearchComponent(this._heroSearchService, this._router) {}
  // Push a search term into the stream.
  void search(String term) => _searchTerms.add(term);
  Future<Null> ngOnInit() async {
    heroes = _searchTerms.stream
        .transform(debounce(new Duration(milliseconds: 300)))
        .distinct()
        .transform(switchMap((term) => term.isEmpty
            ? new Stream<List<Hero>>.fromIterable([<Hero>[]])
            : _heroSearchService.search(term).asStream()));
  }
}

lib/src/dashboard_component.html

<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of heroes"  [routerLink]="['HeroDetail', {id: hero.id.toString()}]"  class="col-1-4">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>
<hero-search></hero-search>

I am confused how StreamController works. I have some questions:

1, In void search(String term) => _searchTerms.add(term);, a term is added to _searchTerms, which is a StreamController, not a Stream. Am I right?

2, The heroes in <a *ngFor="let hero of heroes"> is Stream<List<Hero>> heroes?

3, heroes is initialized in ngOnInit() and a stream is assigned to heroes. I cannot understand how heroes are updated. Can anyone explain the process to me?

4, I am also reading the Custom events session in https://webdev.dartlang.org/angular/guide/template-syntax. The codes are as following. (Example 2)

final _deleteRequest = new StreamController<Hero>();
@Output()
Stream<Hero> get deleteRequest => _deleteRequest.stream;

void delete() {
  _deleteRequest.add(hero);
}

<hero-detail (deleteRequest)="deleteHero($event)" [hero]="currentHero"></hero-detail>

In the above codes, hero is added to _deleteRequest. deleteRequest is the custom event, which is triggered and $event is passed to deleteHero() function. $event is just hero. Am I right? Can I consider deleteRequest to be a event?

5, In the first example, property heroes is connected to a stream. In the second example, a stream is bind to a event deleteRequest. Am I right?

Any hints welcomed. Thanks


Solution

  • Here are some answers to your multipart question:

    1. In void search(String term) => _searchTerms.add(term);, a term is added to _searchTerms, which is a StreamController, not a Stream. Am I right?

    A StreamController, as the name implies, controls a stream. Values get fed into that stream when you call StreamController.add().

    Here is lib/src/hero_search_component.html:

    <div id="search-component">
      <h4>Hero Search</h4>
      <input #searchBox id="search-box"
            (change)="search(searchBox.value)"
            (keyup)="search(searchBox.value)" />
      <div>
        <div *ngFor="let hero of heroes | async"
            (click)="gotoDetail(hero)" class="search-result" >
          {{hero.name}}
        </div>
      </div>
    </div>
    

    Notice: <input ... (keyup)="search(searchBox.value)" />. After every key you type in the input search box (on keyup), the HeroSearchComponent.search(String term) method gets call, which in turn calls StreamController.add(). That is how values get pumped into the stream.

    5, In the first example, property heroes is connected to a stream.

    heroes is a stream obtained as follows: start with the stream from the controller but apply some transformations to it (debounce, etc).

    1. ... $event is just hero. Am I right? Can I consider deleteRequest to be a event?

    Yes the value of $event will be the Hero instance to be deleted. Yes, "deleteRequest" is the name of the custom even being fired.