Implementing Angular2 forms – Beyond basics (part 3)
2016-03-16 16:15
253 查看
In the first part of
this article, we deal with foundations of the form support. We then describe in a second
part more advanced features to make form creation and processing more concise and robust. It’s now time to tackle the form submission.
event is fired and processing remains in the same page.
Simply register processing against this event using the bracket expression. In the following sample, we call the
occurs.
This
feedback, we can use a
We will see in the next section how to handle errors.
This
of the button. This way the value of this attribute will be linked to the provided expression. This can be combined with the
Here is the result.
First in the service. Since the map operator isn’t called in the case of failures, we need to extract the JSON error content from the payload using the catch operator, as described below:
Observables provide operators to configure asynchronous data streams. This aspect is part of Reactive Programming that will be discussed in a following article. We used the map operator in a previous Angular2 article in the section “Interacting
with the Web API”.
This way we will receive the error as JSON object when defining a second callback at the level of the subscribe method in the component. We can then directly handle it.
Now we receive the error payload within the error callback registered in the subscribe method, we can distinguish two kinds of errors to handle within the displayErrors method:
Global errors that notify that the update fails
Server validation errors that are linked to the fields of the form
The method has the responsibility to handle both cases. In the first one, an error property is set with the message. A dedicated component will then use this property to display the message.
For field errors, the method will look for fields with errors and set them within their corresponding controls. All these hints are present in the error content as we can see within the DHC
HTTP client.
Here is its complete implementation.
Server validation errors for fields are displayed the same way as the local ones at the level of field inputs.
To display global errors as Bootstrap does, we need to go further by creating a simple component, as described below. It will leverage the alert* classes of the library.
Simply add an tag in your form to specify where to display the error after having adding the FormErrorComponent component into the directives attribute of the component containing the form:
Here is how such messages will be displayed in the form.
concise and powerful forms.
In this article, we made an effort to split form building and processing into several small components that interact together to provide the company editing feature. All this work contributes to improve code maintainability and reusability, since
it’s possible to reuse most of these components into other forms of the application.
As stated form controls can also leverage observables and reactive programming to make other parts of the application react following user inputs. We will focus on the support of such approaches within Angular 2 in a following article, so stay tuned!
The source code is available in the following Github repository: https://github.com/restlet/restlet-sample-angular2-forms.
this article, we deal with foundations of the form support. We then describe in a second
part more advanced features to make form creation and processing more concise and robust. It’s now time to tackle the form submission.
Handling form submission
Angular 2 automatically applies theNgFormdirective to the HTML form element. The main consequence is that we need to disable the default behavior of browsers and apply the one from Angular 2. That way a specific
event is fired and processing remains in the same page.
Submitting data
To submit data, we need to leverage the submit event of the form with the Angular 2 syntax. This event is triggered when clicking on an HTML submit button.Simply register processing against this event using the bracket expression. In the following sample, we call the
onSubmitmethod of the component when the
submitevent
occurs.
<form [ngFormModel]="companyForm" (submit)="onSubmit()"> (...) <button type="submit">Save</button> (...) </form>
This
onSubmitmethod will leverage the
CompanyServiceservice injected in the component to actually update the company data in the RESTful service. To give the user some
feedback, we can use a
submitPendingproperty to display a spinning icon during the execution of the HTTP request. When response is back, you can hide it and display a message using the Toastr library.
onSubmit() { this.submitPending = true; this.service.updateCompany(this.companyId, this.company).subscribe( company => { toastr.info('Company successfully updated'); this.submitPending = false; }, error => { (...) } ); return false; }
We will see in the next section how to handle errors.
This
submitPendingproperty also allows us to disable the submit button to prevent users from clicking several times. For this we can simply use interpolation for the
disabledattribute
of the button. This way the value of this attribute will be linked to the provided expression. This can be combined with the
pendingproperty of the form control to disable the button as well during asynchronous validation.
<button type="submit" [disabled]="submitPending || companyForm.pending"> Save <span *ngIf="submitPending" class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span> </button>
Here is the result.
Form submission error handling
In the previous section, we intentionally didn’t handle errors that could occur when executing the HTTP request to save the company. To make this processing more robust, we need to handle them. This must be done at two different levels.First in the service. Since the map operator isn’t called in the case of failures, we need to extract the JSON error content from the payload using the catch operator, as described below:
updateCompany(companyId:string,company:Company) { var headers = new Headers(); this.createAuthorizationHeader(headers); headers.append('Content-Type', 'application/json'); return this.http.put( `https://Angular 2.apispark.net/v1/companies/${companyId}`, JSON.stringify(company), { headers: headers }).map(res => res.json()).catch(res => { return Observable.throw(res.json()); }); }
Observables provide operators to configure asynchronous data streams. This aspect is part of Reactive Programming that will be discussed in a following article. We used the map operator in a previous Angular2 article in the section “Interacting
with the Web API”.
This way we will receive the error as JSON object when defining a second callback at the level of the subscribe method in the component. We can then directly handle it.
onSubmit() { this.service.updateCompany(this.companyId, this.company).subscribe( company => { (...) }, error => { this.displayErrors(error); } ); return false; }
Now we receive the error payload within the error callback registered in the subscribe method, we can distinguish two kinds of errors to handle within the displayErrors method:
Global errors that notify that the update fails
Server validation errors that are linked to the fields of the form
The method has the responsibility to handle both cases. In the first one, an error property is set with the message. A dedicated component will then use this property to display the message.
For field errors, the method will look for fields with errors and set them within their corresponding controls. All these hints are present in the error content as we can see within the DHC
HTTP client.
Here is its complete implementation.
displayErrors(error) { if (error.messages) { var messages = error.messages; messages.forEach((message) => { this.companyForm.controls[message.property].setErrors({ remote: message.message }); }); } else { this.error = `${error.reasonPhrase} (${error.code})`; } }
Server validation errors for fields are displayed the same way as the local ones at the level of field inputs.
To display global errors as Bootstrap does, we need to go further by creating a simple component, as described below. It will leverage the alert* classes of the library.
@Component({ selector: 'error', template: ` <div *ngIf="error" class="form-group form-group-sm"> <div class="alert alert-warning alert-dismissible col-md-10 col-sm-10" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> {{error}} </div> </div> ` }) export class FormErrorComponent { @Input() error:string; }
Simply add an tag in your form to specify where to display the error after having adding the FormErrorComponent component into the directives attribute of the component containing the form:
@Component({ directives: [ (...), FormErrorComponent ], template: ` <form [ngFormModel]="companyForm" (submit)="onSubmit()"> (...) <error [error]="error"></error> </form> ` }) export class DetailsComponent { (...) }
Here is how such messages will be displayed in the form.
Conclusion
In this article, we described how to implement forms with Angular 2. We went beyond the basics to show how to leverage the power of Angular 2. We saw how the standard form support of Angular 2 can fit into its component-based approach to implementconcise and powerful forms.
In this article, we made an effort to split form building and processing into several small components that interact together to provide the company editing feature. All this work contributes to improve code maintainability and reusability, since
it’s possible to reuse most of these components into other forms of the application.
As stated form controls can also leverage observables and reactive programming to make other parts of the application react following user inputs. We will focus on the support of such approaches within Angular 2 in a following article, so stay tuned!
The source code is available in the following Github repository: https://github.com/restlet/restlet-sample-angular2-forms.
相关文章推荐
- 深入了解前端路由的实现机制以及angularjs-route-ui的使用
- 结构-行为-样式-angularJs
- [AngularJS] Transforming raw JSON data to meaningful output in AngularJS
- Implementing Angular2 forms – Beyond basics
- 快速搭建Web环境 Angularjs + Express3 + Bootstrap3
- Angular.watch性能问题和ngInfiniteScroll
- AngularJS基本功能
- Angular Chart 使用说明(基于angular工程)
- AngularJS展示数据的ng-bind指令和{{}} 区别
- AngularJS入门(二)
- Angular之$resource
- Angular自定义指令(进阶)
- AngularJS学习(一)——基本的入门程序(配置环境)
- [angularjs] angularjs系列笔记(一)简介
- AngularJS实现鼠标右键事件
- 从 AngularJS 模块定义说起
- AngularJS介绍 - 下一个大框架
- angularjs---思维导图 01
- 细说Angular ng-class
- AngularJS入门(一)