ngModel不能用來把表單控件註冊到父formGroup指令中。否則會報錯
若是你想避免註冊這個表單控件,請在ngModelOptions中指出它是獨立的:html
<input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">
指令頭部算法
selector: '[ngModel]:not([formControlName]):not([formControl])', exportAs: 'ngModel'
拿出別名,用[(ngModel)]
就別跟formControlName
或者formControl
一塊兒用api
別名的用處很大,能夠直接拿到管道內部的內容,這個咱們在以前的文章介紹過瀏覽器
拿到視圖展現的內容 viewModel: any; *跟蹤綁定到指令的名稱。若是父窗體存在,則它 *使用此名稱做爲鍵來檢索此控件的值。 @Input() name!: string; 是否已禁用。 @Input('disabled') isDisabled!: boolean; @Input('ngModel') model: any; name: 在表單控件元素上設置name屬性的另外一種選擇 standalone: 當設置爲true時,「ngModel」將不會向它的父窗體註冊本身,默認值爲false uptateOne:定義表單控件值和有效性更新所依據的事件,默認change type FormHooks = 'change'|'blur'|'submit'; @Input('ngModelOptions') options!: {name?: string, standalone?: boolean, updateOn?: FormHooks}; ngModelChange '事件'類型雙向綁定,經過事件拿到值 @Output('ngModelChange') update = new EventEmitter();
別名的使用app
<input type="text" [(ngModel)]="a" #dir='ngModel' [ngModelOptions]="{updateOne:'blur'}"> <span>{{dir.viewModel}}</span>
https://angular.cn/api/forms/NgForm函數
@Directive({selector: '[ngModelGroup]', exportAs: 'ngModelGroup'}) @Directive({ selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]', //其實我不是很建議把這個寫在最外層 from上,畢竟咱們的按鈕位置都是不固定 host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'}, outputs: ['ngSubmit'], exportAs: 'ngForm' })
其實愈來愈感受這種用法體現了別名的強大之處ui
<form #f="ngForm"> <!-- name是每一個的屬性--> <input name="first" ngModel required #first="ngModel"> <input name="last" ngModel> <button (click)="onSubmit(f)">Submit</button> <button (click)="resetSub(f)">取消</button> </form> onSubmit(f: NgForm) { console.log(f.value) } resetSub(f: NgForm) { f.reset() }
https://angular.cn/api/forms/NgModelGroupthis
@Component({ selector: 'example-app', template: ` <form #f="ngForm" (ngSubmit)="onSubmit(f)"> <p *ngIf="nameCtrl.invalid">Name is invalid.</p> <div ngModelGroup="name" #nameCtrl="ngModelGroup"> <input name="first" [ngModel]="name.first" minlength="2"> <input name="last" [ngModel]="name.last" required> </div> <input name="email" ngModel> <button>Submit</button> </form> <button (click)="setValue()">Set value</button> `, }) export class NgModelGroupComp { name = {first: 'Nancy', last: 'Drew'}; onSubmit(f: NgForm) { console.log(f.value); // {name: {first: 'Nancy', last: 'Drew'}, email: ''} console.log(f.valid); // true } setValue() { this.name = {first: 'Bess', last: 'Marvin'}; } }
上面應該是屬於angular.js遺留過來的功能,不建議使用,spa
選擇器雙向綁定
select[multiple][formControlName] select[multiple][formControl] select[multiple][ngModel]
事件
host: {'(change)': 'onChange($event.target)', '(blur)': 'onTouched()'},
案例一
<label> <select multiple [formControl]="countryControl"> <option *ngFor="let country of countries" [ngValue]="country.sex"> {{ country.name }} </option> </select> </label> 按shift能夠模擬選中多個 countryControl = new FormControl(); countries=[ {name:'aaa',sex:1}, {name:'bbb',sex:2}, {name:'ccc',sex:3} ] //檢測變化 this.countryControl.valueChanges.subscribe(console.log)
案例二在form表單中
<form [formGroup]="profileFormOne"> <label> <select multiple formControlName="firstName"> <option *ngFor="let country of countries" [ngValue]="country.sex"> {{ country.name }} </option> </select> </label> </form> this.profileFormOne.get('firstName').valueChanges.subscribe(console.log)
案例三
<select multiple [(ngModel)]="countryControl" (ngModelChange)="clickChange($event)"> countryControl = []; clickChange(e) { console.log(e); }
跟蹤策略[compareWith]
跟蹤用於跟蹤身份時的選項比較算法
咱們經過經過FormControl構造函數傳遞對象引用來設置默認選項。如今的問題是,當咱們從新填充選項列表(例如,經過HTTP調用)時,對象引用消失了,所選值的模型綁定也丟失了。
爲了解決這個問題,咱們可使用compareWith指令,該指令將再也不比較對象引用,而是使用布爾表達式或函數
<select [compareWith]="compareFn" [formControl]="selectedCountriesControl"> <option *ngFor="let country of countries" [ngValue]="country"> {{country.name}} </option> </select> compareFn(c1: Country, c2: Country): boolean { return c1 && c2 ? c1.id === c2.id : c1 === c2; } 相似於這樣 countries=[ {name:'aaa',id:1}, {name:'bbb',id:2}, {name:'ccc',id:3} ]
咱們看看option
標籤
@Directive({selector: 'option'}) ... @Input('ngValue') set ngValue(value: any) { if (this._select == null) return; this._value = value; this._setElementValue(_buildValueString(this.id, value)); this._select.writeValue(this._select.value); } @Input('value') set value(value: any) { if (this._select) { this._value = value; this._setElementValue(_buildValueString(this.id, value)); this._select.writeValue(this._select.value); } else { this._setElementValue(value); } }
也就是你在option
標籤能夠把經過value
或者ngValue
傳遞數據
選擇器
input[type=range][formControlName] input[type=range][formControl] input[type=range][ngModel]
事件
host: { '(change)': 'onChange($event.target.value)', '(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()' },
跟複選框相似,這個就列舉一個demo吧
const firstName=new FormControl(20), <input type="range" [formControl]="firstName" min="10" max="100">
若是須要禁用的話 [attr.disabled]="true"
仍是要這樣寫,覺得源碼中沒有傳進去拿不到
input[type=radio][formControlName]
input[type=radio][formControl]
input[type=radio][ngModel]
案例
案例一 <form [formGroup]="profileFormOne" > <input type="radio" formControlName="firstName" value="beef" > Beef <input type="radio" formControlName="firstName" value="lamb"> Lamb <input type="radio" formControlName="firstName" value="fish"> Fish </form> 案例二 <input type="radio" [formControl]="firstNames" value="beef" > Beef firstNames=new FormControl() 案例三 其實上面的三個事件也是能夠的 <input type="radio" [(ngModel)]="firstNames" value="beef333" (ngModelChange)="clickChange($event)">
事件
host: {'(change)': 'onChange()', '(blur)': 'onTouched()'},
輸入的值(這個也挺重要的,幫咱們如何思考怎麼寫demo) 提供name
屬性是可選的。若是有多個單選框的話,仍是建議指定下name的值
@Input() name!: string; @Input() formControlName!: string; @Input() value: any;
[pattern][formControlName]
[pattern][formControl]
[pattern][ngModel]
屬性
pattern: string | RegExp
例如
<input name="firstName" [(ngModel)]="firstName" pattern="[a-zA-Z ]*">
input[type=number][formControlName]
input[type=number][formControl]
input[type=number][ngModel]
事件跟前面同樣
當之發生改變的回調函數 registerOnChange(fn: (_: number|null) => void): void { this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); }; } 咱們能夠知道主要使用parseFloat
案例
<input type="number" [formControl]="totalCountControl"> const totalCountControl = new FormControl();
默認狀況下爲全部表單添加novalidate
屬性。
novalidate
用於禁用瀏覽器的原生表單驗證。若是你想在Angular表單中使用原生驗證,只需添加ngNativeValidate
屬性:
<form ngNativeValidate></form>