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
是基类
也就是 FormControl
、FormGroup
和 FormArray
的基类。也就是都具有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(''),
})
])