8

In Angular 2 how do you add an input control in a custom component that will bind to the form control container in the parent component? (FOLLOWING CODE SIMPLIFIED FOR BREVITY)

For example, I have a form component (please note the button disabled binding)

@Component{
selector:'my-form',
template:'
<form [ng-form-model]="myForm">
    <my-special-input></my-special-input>
</form>
<button [disabled]="!myForm.valid">
'
}

Now in my special input component I would like to

@component{
 selector:'my-special-input'
 template:'
    <input ng-control='name' required>
}'

ng-control='name' generates an error "No provider for ControlContainer!" I have searched for solutions and haven't found any that would allow for parent form control container validation.

I would think creating custom reusable input components that get added to a form control container would be a common scenario in Angular 2.

I cant image there there is no way add the input in the custom component to the parent form component in a way that would enable form level validation.

2
  • Why don't you make the input a directive instead? Commented Jan 24, 2016 at 19:33
  • Not sure I got your question right, but if you're looking for something similar to Angular 1's transclude, i.e. take a piece of DOM from your host view and move it within your custom component, you can look for Angular 2's <ng-content></ng-content> Commented May 10, 2016 at 11:04

2 Answers 2

6

Not sure if this is the best way for your scenario, but I think it works.

You can create the Control on the parent element and pass it as @Input to the child. The child can then use it as the control on the form element.

For example (plunk):

@Component({
  selector:'my-special-input'
  template:`
        <input type="text" [ngFormControl]='nameControl' > 
    `
})
export class specialInputComponent implements OnInit{
  @Input() nameControl;
}

@Component({
  selector:'my-form',
  template:`
    <form [ngFormModel]="myForm" >
       <my-special-input [nameControl]="nameControl"></my-special-input>
    </form>
    <button [disabled]="!myForm.valid">Submit</button>
    `,
    directives: [specialInputComponent]
})
export class formComponent{
    nameControl:Control;
    myForm: ControlGroup;

    constructor(){
        this.nameControl = new Control("", Validators.required );
        this.myForm = new ControlGroup({special: this.nameControl});
        }
}

You could probably also pass the ControlGroup to the child and let the child add itself with addControl() but you might have to deal with the update cycle getting a little messy.

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

2 Comments

Thanks! That will work. I tried it the other way around, passing the form to the component / directive but couldn't get it to work.
Glad it worked. I wish it was a better answer. I feel like there must be a better way especially if you want to encapsulate the control behavior within your custom component. I was hoping someone else would chime in.
-1

Form validation with Angular couples the validation with the component.

This leads to the business logic around validation being scattered all over the application in components.

Many times it is better to create a TypeScript based re-usable validation service.

  • This allows the business logic to be centralized in one place.

  • You can unit test this business logic by unit testing the service.

This demo Angular 6 CLI app shows you how to do this.

https://github.com/VeritasSoftware/ts-validator-app-angular6

You might find this useful from your design considerations.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.