首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular2 ControlValueAccessor

Angular2 ControlValueAccessor
EN

Stack Overflow用户
提问于 2016-06-03 08:02:30
回答 2查看 4.6K关注 0票数 0

我正在努力理解ControlValueAccessor是如何精确地工作的。

我用两个不同的控制成分研究了它的行为:

  • 第一个假设提供一个原语值:一个数字。
  • 第二个提供了一个复杂的对象。

因此,简而言之:

代码语言:javascript
复制
class FirstControlComponent implements ControlValueAccessor {
    // ...
    value:number = 10;
    writeValue(value: number) {
        this.value = value;
    }
    // ...
}

class SecondControlComponent implements ControlValueAccessor {
    // ...
    value:any = {};
    writeValue(value: any) {
        this.value = value;
    }
    // ...
}

ControlValueAccessor接口只指定“setter”:writeValue,而没有指定“getter”。

因此,当我将控件绑定到SecondControlComponent时,如下所示:

代码语言:javascript
复制
this.form = this.builder.group({
    controlName: this.builder.control(this.theObject) });

随后在模板中:

代码语言:javascript
复制
<second-component ngControl='controlName'> <second-component>

所有操作都很好,因为init上调用writeValue时引用了现有的theObject对象,因此控件修改了该对象的同一个实例(希望我很清楚)

但是:如果我对FirstControlComponent做了完全相同的事情,,因为值不是作为引用传递的(因为它是一个原语),而是因为 ControlValueAccessor没有提供'setter‘--在我的控件中的值和主机组件中的值没有保持同步.

这是否意味着我们必须传递对象而不是原语来实现ControlValueAccessor的自定义控件?我想不是,所以我想我一定是误会了..。:)

我用得对吗?

任何提示都欢迎!

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2016-06-03 08:54:29

我不清楚您在这里试图做什么,但是ControlValueAccessor是一个您需要为元素注册的实体。就像这样:

代码语言:javascript
复制
const CUSTOM_VALUE_ACCESSOR = new Provider(
    NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => LabelsValueAccessor), multi: true});

@Directive({
  (...)
  providers: [CUSTOM_VALUE_ACCESSOR]
})
export class LabelsValueAccessor implements ControlValueAccessor {
  (...)
}

然后,它将接受部分值更新(来自组件和模板)。当您在输入的组件中设置一个值时(例如),writeValue方法将在您的值访问器中被调用。如果要从值访问器更新输入值,则需要利用Angular2注册的Angular2回调。

有关详细信息,请参阅本文(“NgModel兼容组件”一节):

  • http://restlet.com/blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/
票数 1
EN

Stack Overflow用户

发布于 2019-09-29 07:12:40

在父组件中,我希望输出像这个{someOtherControlName: any, controlName: number}那样的表单,所以子表单的输出必须是number.also (例如),formControl的parentform.patchValue({someOtherControlName: '', controlNmae: 3})值必须正确设置

代码语言:javascript
复制
@Component({
selector: 'parent',
template: `
    <div [formGroup]="form">
    <second-component [formControl]='form.controlName'> <second-component>
    <div formControlName="someOtherControlName"></div>
 export class ParentComponent {
    parentForm = new FormGroup({
       controlName: new FormControl(),  <<<<<======important
       someOtherControlName: new FormControl()
    })
}

在ControlValueAccessor中:

代码语言:javascript
复制
@Component({
selector: 'counter',
template: `
    <div class="number-input" [formGroup]="form">
        <input type="text" class="form-control text-center" formControlName="counter" />
</div>
`,
styleUrls: ['counter.component.scss'],
providers: [
    {
        provide: NG_VALUE_ACCESSOR,
        useExisting: CounterComponent,
        multi: true,
    },
],
})
 export class CounterComponent implements ControlValueAccessor, OnDestroy, OnInit {
   form = new FormGroup({
    counter: new FormControl(0, Validators.required),
   })

    private onChange: (value: any) => void = value => {}
    private onTouched: () => void = () => {}
    myValue: number
    private onDestroy$: Subject<void> = new Subject()
    ngOnInit() {
    this.form.valueChanges
        .pipe(
            tap(value => {
                this.onChange(typeof value === 'number' ? value : value.counter) <<<< important
                this.onTouched()
            }),
            takeUntil(this.onDestroy$)
        )
        .subscribe()
   }

   }
   writeValue(value: number | { counter: number }) {
    this.myValue = typeof value === 'number' ? value : value.counter
    this.form.setValue({ counter: value > 0 ? value : 0 })
    }
   registerOnChange(fn: () => {}) {
    this.onChange = fn
   }
   registerOnTouched(fn: () => {}) {
    this.onTouched = fn
   }
   setDisabledState?(isDisabled: boolean): void {
    // when the parent updates the
    // state of the form control

      if (isDisabled) {
        this.form.disable()
      } else {
        this.form.enable()
      }
   }
   ngOnDestroy(): void {
     this.onDestroy$.next()
     this.onDestroy$.complete()
   }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37609085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档