2

I need to write a component that can be used in a form. I want to publish it as ng-invalid for the form.

that is my form template/view:

    <form  #myForm="ngForm">        
    <domain-base-value  [(ngModel)]="value.value" name="bla" #bla="ngModel">
    </domain-base-value>
    <div [hidden]="myForm.valid || myForm.pristine">
      Form is not valid
    </div>
    </form>

that is domain-base-value component view: <input [(ngModel)]="value" required /> if I run it, the input get ng-invalid but not the domain-base-value and the form. I can move the required to the form, but I want that the child component will have the logic when is it valid and when not. any suggestions?

Brachi
  • 637
  • 9
  • 17

3 Answers3

0

You need to make your sub-component ngModel-compatible by making it implementing a custom value accessor. This way you will be able to use ngModel and directives like ngFormControl to apply validators.

Here is a sample:

const MY_VALUE_ACCESSOR = new Provider(
  NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => MyInputComponent), multi: true});

@Component({
  (...)
  providers: [ MY_VALUE_ACCESSOR ]
})
export class MyInputComponent extends DefaultValueAccessor {
  onChange = (_) => {};
  onTouched = () => {};

  writeValue(value:any):void {
    if (value!=null) {
      super.writeValue(value.toString());
    }
  }

  // call when your internal input is updated
  doOnChange(val) {
    this.onChange(val);
  }
}

For more details, see this article (section "NgModel-compatible component"):

See also this question:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • I'm already bound to ngModel. But I'm asking on validation. You didn't show how to make the child component not valid. I mean to get ng-invalid class. – Brachi Jun 30 '16 at 18:00
0

Use disabled to accomplish this

<form  #myForm="ngForm">
    <domain-base-value  [(ngModel)]="value.value" name="bla" #bla="ngModel">
    </domain-base-value>
    <div [disabled]="!form.valid || form.pristine">
      Form is not valid
    </div>
</form>
byteC0de
  • 5,153
  • 5
  • 33
  • 66
-1

To repeat:

  • You have got a component, which holds an input field.
  • This input field itself is a ngModel and has the attributes ng-invalid
  • Your form, which calls the component does not know about the invalid input field in the domain-base-value component

I think the problem is, that your ngForm does not know about the input field inside your component. My solution would be to add the ngForm as @Input parameter to the domain-base-value component and inside your component add the ngModel to the form. Your form would look like:

<form  #myForm="ngForm">
    <domain-base-value  
        [(ngModel)]="value.value" 
        name="bla" 
        #bla="ngModel"
        [form]="myForm"
    >
    </domain-base-value>
    <div [hidden]="myForm.valid || myForm.pristine">
        Form is not valid
    </div>
 </form>

Inside your component it would look like:

@Component({...})
export class DomainBaseValue implements OnInit {

    @Input() form: NgForm;

    @ViewChild('input1') input1;

    ngOnInit() {
        this.form.addControl(this.input1);
    }

}

This should append the NgModel to your NgForm and you should now see the correct attributes on your form.

Hope this helps.

Eric
  • 31
  • 4