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()

将控件及其所有后代控件标记为“已接触”。

  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传参类似

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

把所有属性变成null

默认AbstractControl 是基类

也就是 FormControlFormGroupFormArray 的基类。也就是都具有reset这个属性

影响的属性,会把他们修改成默认

untouched 未接触,默认为true
touched  接触,默认为false
pristine  干净的,默认为true
dirty	   脏的,默认为false
清空报错信息
g.pristine // 默认的时候 true
g.markAsDirty();
g.pristine // false
g.reset() //清空所有
g.pristine //true

当有脏的兄弟,不会影响兄弟的结果,但是会影响当前和子代

const form = new FormGroup({'g': g, 'c3': c3});
g.markAsDirty();
c3.markAsDirty();
form.pristine //false
g.reset();
form.pristine //false
因为兄弟是脏的,所以清空当前的不会影响兄弟的结果

源码

 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

检查当前组内是否有具有给定名称的启用控件,返回是否启用[就是禁用的相反]

人话就是查找子子属性是否解除禁用的状态,如果禁用就是false,没有禁用就是true

 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- 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(''),
        })
      ])
原文地址:https://www.cnblogs.com/fangdongdemao/p/14233298.html