شروع به کار با AngularJS 2.0 و TypeScript - قسمت یازدهم - کار با فرمها - قسمت دوم
نویسنده: وحید نصیری
تاریخ: ۱۳۹۵/۰۲/۱۶ ۱۳:۳۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
export interface IUser {
id: number;
name: string;
email: string;
password: string;
} <form> <div class="form-group"> <label form="name">Username</label> <input id="name" type="text" class="form-control" /> </div> <div class="form-group"> <label form="email">Email</label> <input id="email" type="text" class="form-control" /> </div> <div class="form-group"> <label form="password">Password</label> <input id="password" type="password" class="form-control" /> </div> <button class="btn btn-primary" type="submit">Submit</button> </form>
import { Component } from '@angular/core';
import { Control, ControlGroup, Validators } from '@angular/common';
@Component({
selector: 'signup-form',
templateUrl: 'app/users/signup-form.component.html'
})
export class SignupFormComponent {
form = new ControlGroup({
name: new Control('', Validators.required),
email: new Control('', Validators.required),
password: new Control('', Validators.required)
});
onSubmit(): void {
console.log(this.form.value);
}
} <form [ngFormModel]="form" (ngSubmit)="onSubmit()"> <div class="form-group"> <label form="name">Username</label> <input id="name" type="text" class="form-control" ngControl="name"/> <label class="text-danger" *ngIf="!form.controls['name'].valid"> Username is required. </label> </div> <div class="form-group"> <label form="email">Email</label> <input id="email" type="text" class="form-control" ngControl="email" #email="ngForm"/> <label class="text-danger" *ngIf="email.touched && !email.valid"> Email is required. </label> </div> <div class="form-group"> <label form="password">Password</label> <input id="password" type="password" class="form-control" ngControl="password" #password="ngForm"/> <label class="text-danger" *ngIf="password.touched && !password.valid"> Password is required. </label> </div> <button class="btn btn-primary" type="submit">Submit</button> </form>
form = new ControlGroup({
name: new Control('', Validators.required),
email: new Control('', Validators.required),
password: new Control('', Validators.required)
}); import { Control, ControlGroup, Validators } from '@angular/common'; <form [ngFormModel]="form" (ngSubmit)="onSubmit()">
<label class="text-danger" *ngIf="!form.controls['name'].valid">
onSubmit(): void {
console.log(this.form.value);
} //same as before...
import { SignupFormComponent } from './users/signup-form.component';
@Component({
//same as before…
template: `
//same as before…
<li><a [routerLink]="['AddUser']">Add User</a></li>
//same as before…
`,
//same as before…
})
@RouteConfig([
//same as before…
{ path: '/adduser', name: 'AddUser', component: SignupFormComponent }
])
//same as before... import { Control, ControlGroup, Validators, FormBuilder } from '@angular/common';
form: ControlGroup;
constructor(formBuilder: FormBuilder) {
this.form = formBuilder.group({
name: ['', Validators.required],
email: ['', Validators.required],
password: ['', Validators.required]
});
} import { Control } from '@angular/common';
export class UsernameValidators {
static cannotContainSpace(control: Control) {
if (control.value.indexOf(' ') >= 0) {
return { cannotContainSpace: true };
}
return null;
}
} { required:true } {
minlength : {
requiredLength : 3,
actualLength : 1
}
} import { UsernameValidators } from './usernameValidators'; name: ['', Validators.compose([Validators.required, UsernameValidators.cannotContainSpace])],
<div class="form-group"> <label form="name">Username</label> <input id="name" type="text" class="form-control" ngControl="name" #name="ngForm" /> <div *ngIf="name.touched && name.errors"> <label class="text-danger" *ngIf="name.errors.required"> Username is required. </label> <label class="text-danger" *ngIf="name.errors.cannotContainSpace"> Username can't contain space. </label> </div> </div>
import {Control} from '@angular/common';
export class EmailValidators {
static email(control: Control) {
var regEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var valid = regEx.test(control.value);
return valid ? null : { email: true };
}
} control(value: Object, validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn) : Control
nameShouldBeUnique(control: Control) {
let name: string = control.value;
return new Promise((resolve) => {
this._userService.isUserNameUnique(<IUser>{ "name": name }).subscribe(
(result: IResult) => {
resolve(
result.result ? null : { 'nameShouldBeUnique': true }
);
},
error => {
resolve(null);
}
);
});
} this.form = _formBuilder.group({
name: ['', Validators.compose([
Validators.required,
UsernameValidators.cannotContainSpace
]),
(control: Control) => this.nameShouldBeUnique(control)], import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '@angular/http';
import { IUser } from './user';
import { IResult } from './result';
@Injectable()
export class UserService {
private _checkUserUrl = '/home/checkUser';
constructor(private _http: Http) { }
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
isUserNameUnique(user: IUser): Observable<IResult> {
let headers = new Headers({ 'Content-Type': 'application/json' }); // for ASP.NET MVC
let options = new RequestOptions({ headers: headers });
return this._http.post(this._checkUserUrl, JSON.stringify(user), options)
.map((response: Response) => <IResult>response.json())
.do(data => console.log("User: " + JSON.stringify(data)))
.catch(this.handleError);
}
} export interface IResult {
result: boolean;
} namespace MVC5Angular2.Controllers
{
public class HomeController : Controller
{
[HttpPost]
public ActionResult CheckUser(User user)
{
var isUnique = new { result = true };
if (user.Name?.Equals("Vahid", StringComparison.OrdinalIgnoreCase) ?? false)
{
isUnique = new { result = false };
}
return new ContentResult
{
Content = JsonConvert.SerializeObject(isUnique, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}),
ContentType = "application/json",
ContentEncoding = Encoding.UTF8
};
}
}
} @Component({
selector: 'signup-form',
templateUrl: 'app/users/signup-form.component.html',
providers: [ UserService ]
})
export class SignupFormComponent {
constructor(private _formBuilder: FormBuilder, private _userService: UserService) { <div *ngIf="name.touched && name.errors"> <label class="text-danger" *ngIf="name.errors.required"> Username is required. </label> <label class="text-danger" *ngIf="name.errors.cannotContainSpace"> Username can't contain space. </label> <label class="text-danger" *ngIf="name.errors.nameShouldBeUnique"> This username is already taken. </label> </div>
<input id="name" type="text" class="form-control" ngControl="name" #name="ngForm" /> <div *ngIf="name.control.pending"> Checking server, Please wait ... </div>
onSubmit(): void {
console.log(this.form.value);
this.form.find('name').setErrors({
invalidData : true
});
} <div *ngIf="name.touched && name.errors"> <label class="text-danger" *ngIf="name.errors.invalidData"> Check the inputs.... </label> </div>
{ name="VahidN", email="email@site.com", password="123"} import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '@angular/http';
import { IUser } from './user';
import { IResult } from './result';
@Injectable()
export class UserService {
private _addUserUrl = '/home/addUser';
constructor(private _http: Http) { }
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
addUser(user: IUser): Observable<IUser> {
let headers = new Headers({ 'Content-Type': 'application/json' }); // for ASP.NET MVC
let options = new RequestOptions({ headers: headers });
return this._http.post(this._addUserUrl, JSON.stringify(user), options)
.map((response: Response) => <IUser>response.json())
.do(data => console.log("User: " + JSON.stringify(data)))
.catch(this.handleError);
}
} [HttpPost]
public ActionResult AddUser(User user)
{
user.Id = 1; //todo: save user and get id from db
return new ContentResult
{
Content = JsonConvert.SerializeObject(user, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}),
ContentType = "application/json",
ContentEncoding = Encoding.UTF8
};
} onSubmit(): void {
console.log(this.form.value);
/*this.form.find('name').setErrors({
invalidData : true
});*/
this._userService.addUser(<IUser>this.form.value)
.subscribe((user: IUser) => {
console.log(`ID: ${user.id}`);
});
}
<input type="text" [(ngModel)]="myModel" (blur)="onBlurMethod()">
export class AppComponent {
myModel: any;
constructor(){
this.myModel = '123';
}
onBlurMethod(){
alert(this.myModel);
}
} export class AppComponent {
searchForm: ControlGroup;
results: Observable<any[]>;
constructor(private http: Http) {
let searchField = new Control();
this.searchForm = new ControlGroup({searchField});
this.results = searchField.valueChanges
.debounceTime(500)
.switchMap((val:string) => {
return this.search(val);
});
} "dependencies": {
"@angular/forms": "^0.1.0",
}, "dependencies": {
"@angular/forms": "^0.1.0",
}, // ...
import {disableDeprecatedForms, provideForms} from '@angular/forms';
// ...
bootstrap(AppComponent, [
disableDeprecatedForms(),
provideForms()
]); import { FormControl } from '@angular/forms'; directives: [REACTIVE_FORM_DIRECTIVES]
import { Validators, REACTIVE_FORM_DIRECTIVES, FormControl, FormGroup } from '@angular/forms'; EXCEPTION: TypeError: Cannot read property 'isSkipSelf' of null
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
}; @NgModule({
imports: [
// module dependencies
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
routing
], buildForm(){
this.form = _fb.group({
field1: [null, Validators.compose([Validators.required, CorssFieldValidators.greaterThan('field2', 'فیلد دو')])],
field2: [null, CorssFieldValidators.requiredIf('field1', 20)],
password: [null, Validators.required],
confirmPassword: [null, Validators.compose([Validators.required, CorssFieldValidators.equal('password')])]
})
} export class CrossFieldValidators {
static greaterThanEqual(controlName: string, label: string): ValidatorFn {
return this.is(controlName, label, 'greaterThanEqual');
}
static greaterThan(controlName: string, label: string): ValidatorFn {
return this.is(controlName, label, 'greaterThan');
}
static lessThan(controlName: string, label: string): ValidatorFn {
return this.is(controlName, label, 'lessThan');
}
static lessThanEqual(controlName: string, label: string): ValidatorFn {
return this.is(controlName, label, 'lessThanEqual');
}
static equal(controlName: string, label: string): ValidatorFn {
return this.is(controlName, label, 'equal');
}
static requiredIf(
controlName: string,
value: any
): ValidatorFn {
let subscribed = false;
const validatorFn = (control: AbstractControl): { [key: string]: any } => {
if (!control.root || !(control.root as FormGroup).controls) return null;
const dependentControl = control.root.get(controlName);
if (!subscribed) {
subscribed = true;
dependentControl.valueChanges.subscribe(() => {
control.updateValueAndValidity();
control.markAsTouched();
});
}
const requiredFn = Validators.required;
return dependentControl.value === value ? requiredFn(control) : null;
};
return validatorFn;
}
private static is(
controlName: string,
label: string,
operator:
| 'equal'
| 'greaterThan'
| 'greaterThanEqual'
| 'lessThan'
| 'lessThanEqual'
): ValidatorFn {
let subscribed = false;
const validatorFn = (control: AbstractControl): { [key: string]: any } => {
const value = control.value;
if (value === null) return null;
if (!control.root || !(control.root as FormGroup).controls) return null;
const dependentControl = control.root.get(controlName);
if (!subscribed) {
subscribed = true;
dependentControl.valueChanges.subscribe(() => {
control.updateValueAndValidity({ emitEvent: operator === 'equal' });
control.markAsTouched();
});
}
const dependentValue = dependentControl.value;
if (dependentValue === null) return null;
let isInvalid = false;
switch (operator) {
case 'equal':
isInvalid = dependentValue !== value;
break;
case 'greaterThan':
isInvalid = parseFloat(dependentValue) >= parseFloat(value);
break;
case 'greaterThanEqual':
isInvalid = parseFloat(dependentValue) > parseFloat(value);
break;
case 'lessThan':
isInvalid = parseFloat(dependentValue) <= parseFloat(value);
break;
case 'lessThanEqual':
isInvalid = parseFloat(dependentValue) < parseFloat(value);
break;
default:
throw 'invalid operator!';
}
return isInvalid ? { [operator]: { label } } : null;
};
return validatorFn;
}
}