keyValuePipe
ngFor 跑到object或者Map類型的資料
<div *ngFor="let item of (data|keyvalue)">{{item.key}}--{{item.value}}</div> data = { userId: 1, id: 1, title: "delectus aut autem", completed: false }; 結果 completed--false id--1 title--delectus aut autem userId--1 排序 <div *ngFor="let item of (data|keyvalue:compareFn)">{{item.key}}--{{item.value}}</div> data = { userId: 1, id: 2, title: 10, completed: 8 }; compareFn(a, b) { return a.value - b.value }
Rxjs Generate
參數:
初始值,條件,重復,最后一個應該是每次值得修飾
for循環 const source = generate(0, x => x < 5, x => x + 1); source.subscribe(val => { console.log(val); }) 最后一個值修飾 const source = generate(0, x => x < 5, x => x + 1,x=>x+'!!!'); source.subscribe(val => { console.log(val); }) 0!!! 1!!! 2!!! 3!!! 4!!!
Rxjs repeat 重復
let soure = of(1).pipe(repeat(3));
soure.subscribe(val => {
console.log(val);
})
//重復3次
-1 的時候一直重復
Snapshot快照 :當不需要Observable 替換品
:id
console.log(this.router.snapshot.paramMap.get('id'));
Form
導入模塊
module
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
@NgModule({
imports:[
FormsModule, ReactiveFormsModule
]
})
ts
第一種
names = new FormControl('');
修改
updateName() {
this.names.setValue('小明')
}
<label>name:
<input type="text" [formControl]="names">
</label>
第二種
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl('')
});
點擊修改值
clickDown() {
this.profileForm.patchValue({
firstName: 'yuanli',
lastName: 'xxx'
})
}
拿到提交的值
onSubmit() {
console.log(this.profileForm.value);
}
ngOnInit(): void {
// 監聽值的變化
this.profileForm.valueChanges.subscribe(val=>{
console.log(val);
console.log(this.profileForm.getRawValue());// 這兩個等價的
})
}
remove(){
this.profileForm.reset() //清空所有
}
html
<h1>{{profileForm.value|json}}</h1>
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label>
firstName : <input type="text" formControlName="firstName">
</label> <br>
<label>
lastName : <input type="text" formControlName="lastName">
</label><br>
<button type="submit">Submit</button>
</form>
Reactive Forms
- AbstractControl
FormControl,FormControl,FormArray的抽象類別。 - FormControl
追蹤某一個表單控制項的欄位值與驗證狀態。 - FormGroup
追蹤某一個表單類別下控制項的欄位值與驗證狀態。 - FormArray追蹤
一群表單控制項的欄位值與驗證狀態。
拿到某個特定的值
取得表單控制項
this.myForm.get('nickName')作為FormControl
取得表單分類
this.myForm.get('groupName')作為FormGroup
取得表單數組
this.myForm.get('arrayName')作為FormArray
取得分組下表單格式或控制項
this.myForm.get('groupName.nickName')
驗證
this.myForm.get('nickName').valid
取得欄位驗證錯誤訊息,若驗證通過回傳null
this.myForm.get('nickName').errors
驗證整個表單是否通過驗證
this.myForm.valid
表單驗證
required
email
minlength
maxlength
pattern
獻上一個完整版
ts
import {Component, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
@Component({
selector: 'app-three',
templateUrl: './three.component.html',
styleUrls: ['./three.component.less']
})
export class ThreeComponent implements OnInit {
// myForm = new FormGroup({
// firstName: new FormControl(''),
// lastName: new FormControl('')
// });
myForm = this.fb.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
address: this.fb.group({
address1: [''],
address2: [''],
state: [''],
zip: [''],
}),
mobiles: this.fb.array([
this.fb.control('')
])
})
addAlias() {
this.mobiles.push(this.fb.control(''))
}
get mobiles() {
return this.myForm.get('mobiles') as FormArray
}
onSubmit() {
console.log(this.myForm.value);// 全部
// alert(this.myForm.controls['firstName'].value)
// alert(this.myForm.get('lastName').value) // 兩種拿到當個值得方式
}
constructor(private fb: FormBuilder) {
}
ngOnInit(): void {
}
}
html
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<label>
FirstName:
<input type="text" formControlName="firstName">
</label> <br>
<label>
lastName:
<input type="text" formControlName="lastName">
</label> <br>
<div formGroupName="address">
<label>
address1:
<input type="text" formControlName="address1">
</label> <br>
<label>
address2:
<input type="text" formControlName="address2">
</label> <br>
<label>
State:
<input type="text" formControlName="state">
</label> <br>
<label>
zip:
<input type="text" formControlName="zip">
</label> <br>
</div>
<div formArrayName="mobiles">
<button (click)="addAlias()">增加</button>
<div *ngFor="let mob of mobiles.controls;let i=index">
<label>
Lable {{i}}:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
<button type="submit" [disabled]="!myForm.valid">Submit</button>
</form>
添加自定義篩選
myForm = this.fb.group({
firstName: ['', Validators.required],
lastName: ['', [Validators.required, this.maxValida]],
/* 為 username 添加3項驗證規則:
* 1.必填, 2.最大長度為10, 3.最小長度為3
* 其中第一個空字符串參數為表單的默認值
*/
'username': [ '', [
Validators.required,
Validators.maxLength(10),
Validators.minLength(3)
]]
})
maxValida(val) {
let len = val.value;
return len > 4 ? null : {error: true};
}
完整代碼
html
<h3 class="text-center">注冊</h3>
<form [formGroup]="registerForm" >
<div class="form-group">
<label for="username">用戶名:</label>
<input formControlName="username"
type="text" id="username" #username
class="form-control" >
<div *ngIf="formErrors.username" class="showerr alert alert-danger" >{{ formErrors.username }}</div>
</div>
</form>
ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { validateRex } from './validate-register';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
// 定義表單
registerForm: FormGroup;
// 表單驗證不通過時顯示的錯誤消息
formErrors = {
username: ''
};
// 為每一項表單驗證添加說明文字
validationMessage = {
'username': {
'minlength': '用戶名長度最少為3個字符',
'maxlength': '用戶名長度最多為10個字符',
'required': '請填寫用戶名',
'notdown': '用戶名不能以下划線開頭',
'only': '用戶名只能包含數字、字母、下划線'
}
};
// 添加 fb 屬性,用來創建表單
constructor(private fb: FormBuilder) { }
ngOnInit() {
// 初始化時構建表單
this.buildForm();
}
// 構建表單方法
buildForm(): void {
// 通過 formBuilder構建表單
this.registerForm = this.fb.group({
/* 為 username 添加3項驗證規則:
* 1.必填, 2.最大長度為10, 3.最小長度為3, 4.不能以下划線開頭, 5.只能包含數字、字母、下划線
* 其中第一個空字符串參數為表單的默認值
*/
'username': [ '', [
Validators.required,
Validators.maxLength(10),
Validators.minLength(3),
validateRex('notdown', /^(?!_)/),
validateRex('only', /^[1-9a-zA-Z_]+$/)
]]
});
// 每次表單數據發生變化的時候更新錯誤信息
this.registerForm.valueChanges
.subscribe(data => this.onValueChanged(data));
// 初始化錯誤信息
this.onValueChanged();
}
// 每次數據發生改變時觸發此方法
onValueChanged(data?: any) {
// 如果表單不存在則返回
if (!this.registerForm) return;
// 獲取當前的表單
const form = this.registerForm;
// 遍歷錯誤消息對象
for (const field in this.formErrors) {
// 清空當前的錯誤消息
this.formErrors[field] = '';
// 獲取當前表單的控件
const control = form.get(field);
// 當前表單存在此空間控件 && 此控件沒有被修改 && 此控件驗證不通過
if (control && control.dirty && !control.valid) {
// 獲取驗證不通過的控件名,為了獲取更詳細的不通過信息
const messages = this.validationMessage[field];
// 遍歷當前控件的錯誤對象,獲取到驗證不通過的屬性
for (const key in control.errors) {
// 把所有驗證不通過項的說明文字拼接成錯誤消息
this.formErrors[field] += messages[key] + '\n';
}
}
}
}
}
validate-register.ts
import { ValidatorFn, AbstractControl } from '@angular/forms';
export function validateRex(type: string, validateRex: RegExp): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
// 獲取當前控件的內容
const str = control.value;
// 設置我們自定義的嚴重類型
const res = {};
res[type] = {str}
// 如果驗證通過則返回 null 否則返回一個對象(包含我們自定義的屬性)
return validateRex.test(str) ? null : res;
}
}
熱模塊更新
修改environmen文件
修改environments/environment.ts文件如下
export const environment = {
production: false,
hmr: true,
};
修改environments/environment.prod.ts文件如下
export const environment = {
production: true,
hmr: false,
};
運行的時候必須加--hmr
參數,這里暫時沒有搞清楚為什么要加,因為根據代碼的修改來看都是由environments文件決定是否需要啟動hmr