Applying angular2 form directives to custom input

2019-05-06 15:00发布

I want to create a custom InputCustom component and use it to create model-driven forms.

My custom component just wraps an input field and uses Bootstrap material design for look'n'feel.

@Component({
 selector:'inputCustom',
 template:`
    <div class="form-group label-floating is-empty">
        <label class="control-label" for="input">Type here</label>
        <input class="form-control" id="input" type="text">
        <p class="help-block">Some help text</p>
        <span class="material-input"></span>
    </div>
`})
class InputCustom{....}

In Angular2 when you create a model-driven form

<form [ngFormModel]="formRef">
    <input type ="email" ngControl="email">
</form>

all Controls present on form elements are registered into a ControlGroup. By using the formRef you can track field values inside controllers.

@Component({...})
class FormController{
    formRef: ControlGroup;
    constructor(...){
        this.form.valueChanges.subscribe(data => console.log('changes',  data));
    }
}

Now, I want people to use my component like this

<form [ngFormModel]="formRef">
    <inputCustom type ="email" ngControl="email">
</form>

Q1: Do I need write my own custom ngControl directive?

Q2: How to propagate ngControl to the inner <input> element wrapped by <inputCustom>?

Q3: How should I register my Control inside the surrounding forms ControlGroup?

3条回答
欢心
2楼-- · 2019-05-06 15:33

I guess a custom ValueAccessor should do.

See
- https://plnkr.co/edit/Bz7wLC5qq7s6Fph1UwpC?p=preview (value accessor provided by DI)

    providers: [provide(NG_VALUE_ACCESSOR, {useClass: UIDropdownComp, multi: true})]
})
export class UIDropdownComp implements ControlValueAccessor {

- http://plnkr.co/edit/slVMz6Kgv6KlnUNMDe3o?p=preview (ngControl injected into the component and value accessor assigned "manually"

export class Address implements ControlValueAccessor{
addressForm: ControlGroup;
    value:any;
     addressForm: ControlGroup;
  constructor(@Optional() ngControl: NgControl, elementRef: ElementRef,fb: FormBuilder) {  
    ngControl.valueAccessor = this;

See also https://github.com/angular/angular/issues/2543

查看更多
太酷不给撩
3楼-- · 2019-05-06 15:48

I see two ways to implement that:

  • Provide your control as parameter of your custom component:

    @Component({
      selector: 'inputCustom',
      template: `
        <input [ngFormControl]="control"/>
      `
    export class FormFieldComponent {
      (...)
      @Input()
      control: Control;
    }
    

    This way your input will automatically takes part of the form defined in the parent component.

  • Implement an ngModel-compliant component. It's a bit longer to implement (you need to implement and register a ControlValueAccessor within a custom directive) but this way you will be able to use directly the ngFormControl and ngModel directly on your custom component.

    <inputCustom type ="email" [ngFormControl]="email">
    

    See this question for more details: Angular 2 custom form input

I think that this article could interest you:

查看更多
We Are One
4楼-- · 2019-05-06 15:55

Angular 2 material which implements custom input form element is a great source of information to see how to implement ValueAccessor.

So just dive in the source code here and have a look at the input component : https://github.com/angular/material2

查看更多
登录 后发表回答