angular11源碼探索十五[表單值的設置修改觸發]

setValue/patchValue

setValue(value: any, options: {
    onlySelf?: boolean,
    emitEvent?: boolean,
    emitModelToViewChange?: boolean,
    emitViewToModelChange?: boolean
  }
  patchValue(value: any, options: {
    onlySelf?: boolean,
    emitEvent?: boolean,
    emitModelToViewChange?: boolean,
    emitViewToModelChange?: boolean
  }
`onlySelf`:默認爲false, 當前修改,不更新父級
`emitEvent`:爲true(默認值)' statusChanges '和 'valueChanges'當控件值被更新時,observable會發出帶有最新狀態和值的事件。當爲false時,不觸發任何事件。
`emitModelToViewChange`: 默認爲true,每一個更改都會觸發一個'onChange'事件到更新視圖。
`emitViewToModelChange`: 默認爲true,會觸發`ngModelChange`事件

patchValue 若是多填參數,將多被忽略掉

resetValue

const  c = new FormControl('initial value');
      c.reset({value: 'initial value', disabled: false});
	c.value  // initial value

value 和getRawValue

fbForm: FormGroup; 
    constructor(
        private  fb: FormBuilder
      ) {
    this.fbForm = this.fb.group({
        firstName: '',
        login: fb.control({value:'aaa',disabled:true}),
      });
    console.log(this.fbForm.value);
        //{firstName: ""}  
    檢索全部值,而不考慮禁用狀態。
    console.log(this.fbForm.getRawValue());
   //{firstName: "", login: "aaa"}

disable/enable

`onlySelf`:默認爲false, 當前修改,不更新父級
`emitEvent`:爲true(默認值)' statusChanges '和 'valueChanges'當控件值被更新時,observable會發出帶有最新狀態和值的事件。當爲false時,不觸發任何事件。

 disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {})
 enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {

ts類型問題

(this.fbForm.get('firstName') as FormControl).setValue('333');
    (<FormControl> (this.fbForm.get('firstName'))).setValue('333');
	fg = new FormGroup({
        'c1': new FormControl('v1'),
        'group': new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}),
        'array': new FormArray([new FormControl('v4'), new FormControl('v5')])
      });
    (fg.get('array') as FormArray).at(1).disable();
    formGroup.get('group') as FormGroup;

markAllAsTouched()

將控件及其全部後代控件標記爲「已接觸」。css

markAllAsTouched(): void {
    this.markAsTouched({onlySelf: true});
    this._forEachChild((control: AbstractControl) => control.markAllAsTouched());
  }
const innerGroupFirstChildCtrl = innerGroup.get('c2') as FormControl;
    innerGroupFirstChildCtrl.touched //false
    formGroup.markAllAsTouched();
	formGroup.touched //true

markAsTouched()

markAsTouched(opts: {onlySelf?: boolean} = {}): void {
    (this as {touched: boolean}).touched = true;

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsTouched(opts);
    }
  }

markAsDirty傳參相似html

markAsDirty

markAsDirty(opts: {onlySelf?: boolean} = {}): void {
    (this as {pristine: boolean}).pristine = false;

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsDirty(opts);
    }
  }
  pristine [乾淨]   爲修改UI中的值,默認爲true 
  是否是矇蔽了
   console.log(this.fbForm.dirty); [髒的]    // false
   this.fbForm.markAsDirty()
   console.log(this.fbForm.dirty);    // true
   this.fbForm.markAsDirty({onlySelf:true}) //僅當前控件修改
						爲false所有查找

reset

把全部屬性變成nullweb

默認AbstractControl 是基類ide

也就是 FormControlFormGroupFormArray 的基類。也就是都具備reset這個屬性ui

影響的屬性,會把他們修改爲默認this

untouched 未接觸,默認爲true
touched  接觸,默認爲false
pristine  乾淨的,默認爲true
dirty	   髒的,默認爲false
清空報錯信息
g.pristine // 默認的時候 true
g.markAsDirty();
g.pristine // false
g.reset() //清空全部
g.pristine //true

當有髒的兄弟,不會影響兄弟的結果,可是會影響當前和子代code

const form = new FormGroup({'g': g, 'c3': c3});
g.markAsDirty();
c3.markAsDirty();
form.pristine //false
g.reset();
form.pristine //false
由於兄弟是髒的,因此清空當前的不會影響兄弟的結果

源碼component

onlySelf 是否讓父級知道修改,默認false,就是讓父級知道
 emitEvent 是否觸發statusChanges, valueChanges
reset(value: any = {}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
    this._forEachChild((control: AbstractControl, name: string) => {
      control.reset(value[name], {onlySelf: true, emitEvent: options.emitEvent});
    });
    this._updatePristine(options);
    this._updateTouched(options);
    this.updateValueAndValidity(options);
  }

FormGroup.contains

檢查當前組內是否有具備給定名稱的啓用控件,返回是否啓用[就是禁用的相反]orm

人話就是查找子子屬性是否解除禁用的狀態,若是禁用就是false,沒有禁用就是truehtm

contains(controlName: string): boolean {
    return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled;
  }

css

這個主要給input 添加class

export const ngControlStatusHost = {
  '[class.ng-untouched]': 'ngClassUntouched', 沒觸摸
  '[class.ng-touched]': 'ngClassTouched',  觸摸
  '[class.ng-pristine]': 'ngClassPristine',乾淨的
  '[class.ng-dirty]': 'ngClassDirty',     髒的
  '[class.ng-valid]': 'ngClassValid',    無效的
  '[class.ng-invalid]': 'ngClassInvalid', 有效的
  '[class.ng-pending]': 'ngClassPending', 進行中
};
 * * ng-valid
 * * ng-invalid
 * * ng-pending
 * * ng-pristine
 * * ng-dirty
 * * ng-untouched
 * * ng-touched
就是默認class裏面有這些屬性
默認 class="ng-untouched ng-pristine ng-invalid"
			沒有觸摸     乾淨的      若是沒有設置校驗就是經過校驗的[就是有效的]
當失去焦點就變成
	['ng-invalid', 'ng-pristine', 'ng-touched']
當設置值

使用方法

使用方法
  <div class="aaa">
    <input type="text" formControlName="firstName" class="bbb">
  </div>
css使用
.aaa .ng-dirty {
  border-left: 10px solid #42A948; /* green */
  background-color: red;
}
.bbb.ng-dirty{
  background-color: #d49d9d;
}

關於css的使用

https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

默認寫的組件的css只適用本組件

:host

:host(.active) {
  border-width: 3px;
}
該:host選擇是針對主機元素的惟一途徑。您沒法使用其餘選擇器從組件內部訪問host元素,由於它不是組件本身的模板的一部分。host元素位於父組件的模板中。
是把這個組件的大盒子做爲目標,前提大盒子有這個class
該:host-context()選擇器的外觀在組件**host元素**的**任何祖先**,直到文檔根CSS類。:host-context()與其餘選擇器組合使用時,該選擇器頗有用。
例如
:host-context(.theme-light) h2 {
  background-color: #eef;
}

https://angular.io/guide/view-encapsulation

考慮影子DOM解決css的問題

頁面上

<hero-details _nghost-pmm-5>
  <h2 _ngcontent-pmm-5>Mister Fantastic</h2>
  <hero-team _ngcontent-pmm-5 _nghost-pmm-6>
    <h3 _ngcontent-pmm-6>Team</h3>
  </hero-team>
</hero-detail>

若是想深刻了解影子組件能夠看看我寫的web組件的文章

html 寫法

<input type="radio" formControlName="food" name="drink" value="chicken">
  <input type="radio" formControlName="food" name="drink" value="chicken12">

<form [formGroup]="form">
      <div formArrayName="cities">
        <div *ngFor="let city of cityArray.controls; let i=index">
          <input [formControlName]="i">
        </div>
      </div>
</form>
====
 <div [formGroup]="form">
      <div formArrayName="sex">
        <div *ngFor="let city of sex.controls; let i=index" [formGroupName]="i">
          <input formControlName="name1">
          <input formControlName="name2">
        </div>
      </div>
     </div>

  this.form = new FormGroup({
      sex: new FormArray([
        new FormGroup({
          name1:new FormControl(''),
          name2:new FormControl(''),
        })
      ])
相關文章
相關標籤/搜索