In the recent article, I integrated ngrx/store as a redux implementation to Echoes Player. Until this article, the search was static with one hard coded search query. In this article, I’m sharing my insights on migrating more features from AngularJS and implementing ng-model with ngrx.
In Echoes Player with AngularJS, this template is part of the “search-panel” component. It renders the search box to the top of the player:
<div class="search-panel">
<form class="navbar-form form-search navbar-left" ng-submit="vm.search()">
<div class="form-group">
<input placeholder="Explore Media" type="search" class="form-control" autocomplete="off"
ng-model="vm.params.q"
ng-change="vm.resetPageToken()">
<button class="btn btn-transparent btn-submit" type="submit" title="search with echoes">
<i class="las la-search"></i>
</button>
</div>
</form>
</div>
The migration of the html code above is quite simple (I mentioned it in 3 more steps to prepare your AngularJS to Angular (+2)) in Angular (+2):
Notice the ngModel is both bind with a value (using the binding [] brackets) and both syncs back to its variable (as an event with () ) - This the 2-way binding we’ve been used to from AngularJS. This template goes inside the youtube-videos template. Here is the full template:
<div class="navbar-header">
<div class="search-panel">
<!-- SEARCH FORM -->
<form class="navbar-form form-search navbar-left">
<div class="form-group">
<input placeholder="Explore Media" type="search" class="form-control" autocomplete="off"
[(ngModel)]="searchQuery"
(input)="resetPageToken()"
>
<button class="btn btn-transparent btn-submit" type="submit" title="search with echoes"
(click)="search()">
<i class="las la-search"></i>
</button>
</div>
</form>
</div>
</div>
To support the new search feature, the component’s class needs to be updated with:
import {
Component,
EventEmitter,
Input,
Output,
ChangeDetectionStrategy,
} from "@angular/core"
import { NgModel } from "@angular/common"
import { Store } from "@ngrx/store"
import { YoutubeSearch } from "../core/services/youtube.search"
import { YoutubeList } from "../core/components/youtube-list/youtube-list"
@Component({
selector: "youtube-videos.youtube-videos",
template: require("./youtube-videos.html"),
directives: [YoutubeList, NgModel],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class YoutubeVideos {
videos: any
searchQuery: string = "tremonti"
constructor(private youtubeSearch: YoutubeSearch, public store: Store<any>) {
this.videos = this.store.select("videos")
this.search()
}
ngOnInit() {}
search() {
this.youtubeSearch.search(this.searchQuery, false)
}
playSelectedVideo(media) {
console.log("playing", media)
}
resetPageToken() {
this.youtubeSearch.resetPageToken()
}
}
The last change goes to the youtube search service - this is where the actual search logics happens and where NgRx/store goes into action.
I added a new function ”resetPageToken”, which purpose is to reset the pageToken property in the configuration object that is used in the youtube search request.
This function also dispatched a new action, ‘RESET’, which resets the videos list in the store. It is also being called in the search function if a new search is request by Echoes:
resetPageToken () {
this._config.set('pageToken', '');
this.store.dispatch({ type: RESET });
}
This is the result: