4

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?

1
  • This used to be soooooo simple in Angular 1.x, so painful now : ( Commented Mar 8, 2016 at 19:31

3 Answers 3

3

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:

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.