Oren Farhi

Written by Oren Farhi, Senior Front End Engineer & Javascript Consultant, follow me on

Angular (2+) & NgRx/store: The NgModel In Between Use Case (from Angular 1)

February 19, 2016

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.

From Angular 1 To Angular (+2): NgModel Template Syntax

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="fa fa-search"></i>
			</button>
		</div>
	</form>

</div>
  • I removed some attributes and html code to make this code simpler for this post.

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):

  1. ng-model is converted to ([ngModel])
  2. ng-change is converted to (input)
  3. instead of using ng-submit, I used a simple (click) event on the search button

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="fa fa-search"></i>
				</button>
			</div>
		</form>
	</div>
</div>

Updating Youtube Videos Component Class

To support the new search feature, the component’s class needs to be updated with:

  1. searchQuery” property which will hold the search string value
  2. Updating the search function with the new ”searchQuery
  3. resetPageToken” function which will reset the pageToken property when the search query  changes
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();
	}
}

Updating Youtube Search Service With a New NgRx Action

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:

Screen Shot 2016-02-19 at 3.45.55 PM

 


Oren Farhi

Written by Oren Farhi, Senior Front End Engineer & Javascript Consultant, follow me on

My Consulting Packages

I offer code reviews (Angular, NgRx, React, Javascript), workshops, Consulting and Development. Feel free to reach out thru the below forms.

premium
reactive
reinvented