Using Angular's ngModel directive

Once the forms module is imported, you can start using Angular's template-driven features, and, specifically, the extremely useful ngModel directive.

ngModel is an extensible directive that includes built-in support for two-way binding between component fields or properties and standard form elements.

Let's use ngModel in ProductFormComponent:

  1. Create a new model at src/app/model/new-product.ts:
export interface NewProduct {
title: string;
description: string;
category: string;
}
  1. Re-export the new model as part of the src/app/model/index.ts file:

export * from './new-product';

  1. In ProductFormComponent, initialize a new product as a field in the component:

import { Category, NewProduct } from '../../../model';

export class ProductFormComponent {
@Input() categories: Category[];

product: NewProduct = {
title: '',
description: '',
category: '',
};

}
  1. In the ProductFormComponent template, use ngModel to bind form elements to corresponding product data values using the two-way binding format:
<form>
<div>
<label for="title">Title</label>
<input id="title" name="title" [(ngModel)]="product.title" />
</div>
<div>
<label for="description">Description</label>
<textarea id="description" name="description"
[(ngModel)]="product.description"></textarea>
</div>
<div>
<label for="category">Category</label>
<select id="category" name="category" [(ngModel)]="product.category">
<option value=''>Select category..</option>
<option *ngFor="let c of categories" [value]="c.name">{{
c.name }}</option>
</select>
</div>
<div class="actions-panel">
<button>Save</button>
<button>Cancel</button>
</div>
</form>

With that in place, the form elements are now bound to the product data property in the component, and vice versa! This means that changing the component data synchronizes the form elements, as well as keeping the data in your component updated as the user manipulates the form.

At this moment, the product field in the component state reflects what the user populates as part of the form. Now let's implement the cancel and save functionality:

  1. Implement creating a new product in ProductsService as follows:
...
import { Product, NewProduct } from '../../../model';
...
export class ProductsService {
...
addProduct(product: NewProduct) {
return this.http
.post(`${this.apiUri}products/slim`, product)
.toPromise()
.then(result => result as Product);
}
}
The API action, in this case, should allow anonymous access. Usually, real-life apps that involve authoring data include authentication. In such cases, it mostly requires the app to send a token with each request, which is first generated by a user login.
  1. Bind the click events on the following buttons in the ProductFormComponent template with the onSubmit event handler function defined in the component:

<div class="actions-panel">
<button (click)="onSubmit(true)">Save</button>
<button (click)="onSubmit(false)">Cancel</button>
</div>
  1. Implement the submit callback in ProductFormComponent, and then emit an event to be handled by the parent component. Include the product payload in case the user chooses to save; otherwise, emit null, as shown here:
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
...
export class ProductFormComponent implements OnInit {
@Output() productSubmit = new EventEmitter<NewProduct>();
...
onSubmit(ok) {
this.productSubmit.emit(ok ? this.product : null);
}

}
  1. Bind the productSubmit event in the ProductEditPageComponent template with the onProductSubmit event handler function defined in the component, and then pass it the payload:
<div *ngIf="categories">
<app-product-form
[categories]="categories"
(productSubmit)="onProductSubmit($event)"
>
</app-product-form>
</div>

<app-busy *ngIf="isBusy"></app-busy>
  1. Implement onProductSubmit in the ProductEditPageComponent class with the following settings:
    1. If the payload product is null, use Angular's location abstraction to navigate back.
    2. Otherwise, use ProductsService to add the product, and then navigate back:
...
import { Category, NewProduct } from '../../../model';
import { Location } from '@angular/common';
import { ProductsService } from '../../core/services/products.service';
...
export class ProductEditPageComponent implements OnInit {
...
constructor(
private readonly location: Location,
private readonly categoriesService: CategoriesService,
private readonly productsService: ProductsService,
) { }
...
onProductSubmit(newProduct: NewProduct) {
if (!newProduct) {
this.location.back();
} else {
this.isBusy = true;
try {
this.productsService.addProduct(newProduct)
.then(o => this.location.back());
} finally {
this.isBusy = false;
}
}
}
}

That's it! You can now run the app and try to create a new product. Currently, the app expects the user to enter a valid input on their own, but we will implement form validation in the next section.

Angular provides another directive: ngSubmit, which you can use with event binding on the form element instead of the submit button.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.97.216