New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty controls are invalid when a [required]="false" property is defined #5976

Closed
frickt opened this Issue Dec 17, 2015 · 17 comments

Comments

Projects
None yet
@frickt

frickt commented Dec 17, 2015

small example:

import {Component} from 'angular2/core'
import {FORM_DIRECTIVES, Control} from "angular2/common";

@Component({
     selector: "login-comp",
     directives: [FORM_DIRECTIVES],
     template: '<input type="text" [(ngModel)]="login" [ngFormControl]="loginControl" [required]="isRequired()">'
})
export class App {
 loginControl: Control = new Control('');
 login:string = "";

 isRequired(){
   return false;
 }
}

plnkr for alpha.54

http://plnkr.co/edit/nPlfg2uNAMYTkc5gBWTh?p=preview

@ericmartinezr

This comment has been minimized.

Show comment
Hide comment
@ericmartinezr

ericmartinezr Dec 17, 2015

Contributor

@frickt required is an attribute, you must add attr to it.

... [attr.required]="isRequired()">
Contributor

ericmartinezr commented Dec 17, 2015

@frickt required is an attribute, you must add attr to it.

... [attr.required]="isRequired()">
@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Dec 17, 2015

Member

@ericmartinezr this should work with binding to properties. And there is a required property: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#Properties

Generally speaking we do prefer binding to properties. Currently the main use case for binding to attributes are: aria support and attributes one would like to add for styling

Member

pkozlowski-opensource commented Dec 17, 2015

@ericmartinezr this should work with binding to properties. And there is a required property: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#Properties

Generally speaking we do prefer binding to properties. Currently the main use case for binding to attributes are: aria support and attributes one would like to add for styling

@thelgevold

This comment has been minimized.

Show comment
Hide comment
@thelgevold

thelgevold Dec 17, 2015

Contributor

Different implementation, I know, but I have been using the built in form validators for this. I like this approach since it enables me to manage all validators from a central location.

constructor(fb: FormBuilder) {
    this.form = fb.group({
        "firstName": ['', Validators.required],
        "zip": ['', Validators.compose([zipValidator])],
    });
}

Working example here: http://www.syntaxsuccess.com/viewarticle/forms-and-validation-in-angular-2.0

Contributor

thelgevold commented Dec 17, 2015

Different implementation, I know, but I have been using the built in form validators for this. I like this approach since it enables me to manage all validators from a central location.

constructor(fb: FormBuilder) {
    this.form = fb.group({
        "firstName": ['', Validators.required],
        "zip": ['', Validators.compose([zipValidator])],
    });
}

Working example here: http://www.syntaxsuccess.com/viewarticle/forms-and-validation-in-angular-2.0

@slintes

This comment has been minimized.

Show comment
Hide comment
@slintes

slintes Feb 16, 2016

Hi, I have the same problem, I'm setting required and readonly based on a checkbox value, see this example:

http://plnkr.co/edit/XM8QTwkr3B4nzc40gEpx?p=preview

slintes commented Feb 16, 2016

Hi, I have the same problem, I'm setting required and readonly based on a checkbox value, see this example:

http://plnkr.co/edit/XM8QTwkr3B4nzc40gEpx?p=preview

@zoechi

This comment has been minimized.

Show comment
Hide comment
@zoechi

zoechi Feb 17, 2016

Contributor

If you want the requiredattribute to be remove the value needs to be null not false

 isRequired(){
   return null;
 }
Contributor

zoechi commented Feb 17, 2016

If you want the requiredattribute to be remove the value needs to be null not false

 isRequired(){
   return null;
 }
@slintes

This comment has been minimized.

Show comment
Hide comment
@slintes

slintes Feb 17, 2016

mh, at least in Chrome I see that required is removed with the false value from the checkbox, same for readonly the other way around, with [required]="checked" [readonly]="!checked", see my plunker.
For now I switched to using FormBuilder and a custom validator for checkbox + input on the model side...

slintes commented Feb 17, 2016

mh, at least in Chrome I see that required is removed with the false value from the checkbox, same for readonly the other way around, with [required]="checked" [readonly]="!checked", see my plunker.
For now I switched to using FormBuilder and a custom validator for checkbox + input on the model side...

@awerlang

This comment has been minimized.

Show comment
Hide comment
@awerlang

awerlang Mar 1, 2016

Contributor

[required] is used to initialize a validator for the control. After that, it would always validate even if the required attribute is removed. This behavior diverges from ng1 ng-required.

For a conditional required, you need a custom validator and call updateValueAndValidity() to revalidate. If you want to preserve the required attribute, you'll need to use the attr.required syntax, only for screen readers perhaps.

See comment: #6824 (comment)

Contributor

awerlang commented Mar 1, 2016

[required] is used to initialize a validator for the control. After that, it would always validate even if the required attribute is removed. This behavior diverges from ng1 ng-required.

For a conditional required, you need a custom validator and call updateValueAndValidity() to revalidate. If you want to preserve the required attribute, you'll need to use the attr.required syntax, only for screen readers perhaps.

See comment: #6824 (comment)

@slintes

This comment has been minimized.

Show comment
Hide comment
@slintes

slintes Mar 2, 2016

I use a 1 custom validator for both checkbox and text input now. Code snippets (exposeToFrontend is the checkbox, exposeUrl the text input):

this.formControls = this._fb.group({
            expose: this._fb.group({
                exposeToFrontend: [],
                exposeUrl: []
            },{
                validator: MyValidators.checkboxInputValidator("exposeToFrontend", "exposeUrl", "exposeUrlRequired")
            })
        });
    public static checkboxInputValidator(checkboxName: string, inputName: string, errorCode: string) {
        return (controlGroup: ControlGroup): {[key: string]: any} => {
            let checkbox = controlGroup.controls[checkboxName].value;
            let input = controlGroup.controls[inputName].value;
            if (checkbox && !input) {
                this.addError(inputName, controlGroup.controls[inputName], errorCode);
            }
            else {
                this.removeError(inputName, controlGroup.controls[inputName], errorCode);
            }
            return null;
        }
    }

slintes commented Mar 2, 2016

I use a 1 custom validator for both checkbox and text input now. Code snippets (exposeToFrontend is the checkbox, exposeUrl the text input):

this.formControls = this._fb.group({
            expose: this._fb.group({
                exposeToFrontend: [],
                exposeUrl: []
            },{
                validator: MyValidators.checkboxInputValidator("exposeToFrontend", "exposeUrl", "exposeUrlRequired")
            })
        });
    public static checkboxInputValidator(checkboxName: string, inputName: string, errorCode: string) {
        return (controlGroup: ControlGroup): {[key: string]: any} => {
            let checkbox = controlGroup.controls[checkboxName].value;
            let input = controlGroup.controls[inputName].value;
            if (checkbox && !input) {
                this.addError(inputName, controlGroup.controls[inputName], errorCode);
            }
            else {
                this.removeError(inputName, controlGroup.controls[inputName], errorCode);
            }
            return null;
        }
    }
@udos86

This comment has been minimized.

Show comment
Hide comment
@udos86

udos86 May 30, 2016

Stumbled over this a couple of days ago.

In my opinion this behavior perhaps should be reconsidered because it doesn't feel one hundred percent naturally. When applying Validators.required programmatically no required attribute is added in the DOM. Shouldn't it be there for a semantic reason? I can see the advantage of not having to deal with browser default validation messages on submit, though.

Otherwise as soon as you add [required] in markup, Validators.required is implicitly set, no matter if you bind [required]="true"or [required]="false". Falling back to [attr.required] seems not intuitive when there is a [required] property at the same time.

udos86 commented May 30, 2016

Stumbled over this a couple of days ago.

In my opinion this behavior perhaps should be reconsidered because it doesn't feel one hundred percent naturally. When applying Validators.required programmatically no required attribute is added in the DOM. Shouldn't it be there for a semantic reason? I can see the advantage of not having to deal with browser default validation messages on submit, though.

Otherwise as soon as you add [required] in markup, Validators.required is implicitly set, no matter if you bind [required]="true"or [required]="false". Falling back to [attr.required] seems not intuitive when there is a [required] property at the same time.

@westor21

This comment has been minimized.

Show comment
Hide comment
@westor21

westor21 May 31, 2016

Coming from large angular1 projects, it's unacceptable, not to have a bindable [required] with working validation as pendant to ng-required.

westor21 commented May 31, 2016

Coming from large angular1 projects, it's unacceptable, not to have a bindable [required] with working validation as pendant to ng-required.

@Zefling

This comment has been minimized.

Show comment
Hide comment
@Zefling

Zefling Jun 3, 2016

Same problem whit Material2 input on RC1. If required is at false and control says is not required, the field is still required.

Zefling commented Jun 3, 2016

Same problem whit Material2 input on RC1. If required is at false and control says is not required, the field is still required.

@zoechi

This comment has been minimized.

Show comment
Hide comment
@zoechi

zoechi Jun 3, 2016

Contributor

As far as I know currently attributes for validators required, minlength, pattern, ... need to be static HTML and can't be set by bindings.

Looks like a dup of #7393

Contributor

zoechi commented Jun 3, 2016

As far as I know currently attributes for validators required, minlength, pattern, ... need to be static HTML and can't be set by bindings.

Looks like a dup of #7393

@westor21

This comment has been minimized.

Show comment
Hide comment
@westor21

westor21 Jun 3, 2016

I think, that is a showstopper for many of us migrating angular1 to angular2 - we can currently not implement all of our app logic.

westor21 commented Jun 3, 2016

I think, that is a showstopper for many of us migrating angular1 to angular2 - we can currently not implement all of our app logic.

@zoechi

This comment has been minimized.

Show comment
Hide comment
@zoechi

zoechi Jun 3, 2016

Contributor

You can use model driven forms and add validators there with full control.

Contributor

zoechi commented Jun 3, 2016

You can use model driven forms and add validators there with full control.

@kara

This comment has been minimized.

Show comment
Hide comment
@kara

kara Aug 29, 2016

Contributor

Should have been fixed by #11116.

Contributor

kara commented Aug 29, 2016

Should have been fixed by #11116.

@kara kara closed this Aug 29, 2016

@amdani786

This comment has been minimized.

Show comment
Hide comment
@DeepzSandra

This comment has been minimized.

Show comment
Hide comment
@DeepzSandra

DeepzSandra Mar 14, 2018

Angular 2 Form Validation Using Validators WIth An Element That Is Dynamically Built Using *ngIf
see this example
constructor(
private QRService:QRService,
fb: FormBuilder
){
this.title = 'My Form';
this.showDeliveryTypes = false;
this.complexForm = fb.group({
'number' : [null, Validators.required],
'dateofbirth' : [null, Validators.required],
'delivery' : [null, Validators.required],
'location' : [null, Validators.required], //validates even if these aren't included using *ngIf
'options' : [null, Validators.required] //validates even if these aren't included using *ngIf
})

};
thanks

DeepzSandra commented Mar 14, 2018

Angular 2 Form Validation Using Validators WIth An Element That Is Dynamically Built Using *ngIf
see this example
constructor(
private QRService:QRService,
fb: FormBuilder
){
this.title = 'My Form';
this.showDeliveryTypes = false;
this.complexForm = fb.group({
'number' : [null, Validators.required],
'dateofbirth' : [null, Validators.required],
'delivery' : [null, Validators.required],
'location' : [null, Validators.required], //validates even if these aren't included using *ngIf
'options' : [null, Validators.required] //validates even if these aren't included using *ngIf
})

};
thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment