Angular: Problem with form validation in template driven form










0















I'm developing a web application using Angular 6. I have a question: I would like to create some custom components that are inspired by the components of HTML input. For example:



CustomComponent.ts (typescript)



 @Component(
selector: 'custom-component',
templateUrl: './custom-component.html',
providers: [

provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => InputTextComponent)

]
)
export class CustomComponent

@Input() name: string;
@Input() isRequired: boolean;



CustomComponent.html (template)



<input type="text"
[attr.name]="name"
[required] = "isRequired"
/>


I have this problem. Suppose we use my component in this template:



<form #myForm="ngForm" ngNativeValidate>
<custom-component
name="myName"
[isRequired] = true
ngModel
></custom-component>
<button type="submit" (click)="method()">Click</button>


The required attribute it's initialized correctly in the <input type="text/> (wrapped component of <custom-component>). The problem is this (it's an Angular problem!): in this code of usage:



 method() 
console.log(this.myForm.valid);



The object myForm.valid (where myForm is associated with #myForm in the previous template) return always the true value, even if nothing is entered in the text field. This behavior is wrong: I would like this value to be false if I do not insert anything in the required field.
Anyone can help me?










share|improve this question


























    0















    I'm developing a web application using Angular 6. I have a question: I would like to create some custom components that are inspired by the components of HTML input. For example:



    CustomComponent.ts (typescript)



     @Component(
    selector: 'custom-component',
    templateUrl: './custom-component.html',
    providers: [

    provide: NG_VALUE_ACCESSOR,
    multi: true,
    useExisting: forwardRef(() => InputTextComponent)

    ]
    )
    export class CustomComponent

    @Input() name: string;
    @Input() isRequired: boolean;



    CustomComponent.html (template)



    <input type="text"
    [attr.name]="name"
    [required] = "isRequired"
    />


    I have this problem. Suppose we use my component in this template:



    <form #myForm="ngForm" ngNativeValidate>
    <custom-component
    name="myName"
    [isRequired] = true
    ngModel
    ></custom-component>
    <button type="submit" (click)="method()">Click</button>


    The required attribute it's initialized correctly in the <input type="text/> (wrapped component of <custom-component>). The problem is this (it's an Angular problem!): in this code of usage:



     method() 
    console.log(this.myForm.valid);



    The object myForm.valid (where myForm is associated with #myForm in the previous template) return always the true value, even if nothing is entered in the text field. This behavior is wrong: I would like this value to be false if I do not insert anything in the required field.
    Anyone can help me?










    share|improve this question
























      0












      0








      0








      I'm developing a web application using Angular 6. I have a question: I would like to create some custom components that are inspired by the components of HTML input. For example:



      CustomComponent.ts (typescript)



       @Component(
      selector: 'custom-component',
      templateUrl: './custom-component.html',
      providers: [

      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => InputTextComponent)

      ]
      )
      export class CustomComponent

      @Input() name: string;
      @Input() isRequired: boolean;



      CustomComponent.html (template)



      <input type="text"
      [attr.name]="name"
      [required] = "isRequired"
      />


      I have this problem. Suppose we use my component in this template:



      <form #myForm="ngForm" ngNativeValidate>
      <custom-component
      name="myName"
      [isRequired] = true
      ngModel
      ></custom-component>
      <button type="submit" (click)="method()">Click</button>


      The required attribute it's initialized correctly in the <input type="text/> (wrapped component of <custom-component>). The problem is this (it's an Angular problem!): in this code of usage:



       method() 
      console.log(this.myForm.valid);



      The object myForm.valid (where myForm is associated with #myForm in the previous template) return always the true value, even if nothing is entered in the text field. This behavior is wrong: I would like this value to be false if I do not insert anything in the required field.
      Anyone can help me?










      share|improve this question














      I'm developing a web application using Angular 6. I have a question: I would like to create some custom components that are inspired by the components of HTML input. For example:



      CustomComponent.ts (typescript)



       @Component(
      selector: 'custom-component',
      templateUrl: './custom-component.html',
      providers: [

      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => InputTextComponent)

      ]
      )
      export class CustomComponent

      @Input() name: string;
      @Input() isRequired: boolean;



      CustomComponent.html (template)



      <input type="text"
      [attr.name]="name"
      [required] = "isRequired"
      />


      I have this problem. Suppose we use my component in this template:



      <form #myForm="ngForm" ngNativeValidate>
      <custom-component
      name="myName"
      [isRequired] = true
      ngModel
      ></custom-component>
      <button type="submit" (click)="method()">Click</button>


      The required attribute it's initialized correctly in the <input type="text/> (wrapped component of <custom-component>). The problem is this (it's an Angular problem!): in this code of usage:



       method() 
      console.log(this.myForm.valid);



      The object myForm.valid (where myForm is associated with #myForm in the previous template) return always the true value, even if nothing is entered in the text field. This behavior is wrong: I would like this value to be false if I do not insert anything in the required field.
      Anyone can help me?







      html angular forms components






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 13 '18 at 15:48









      claudiozclaudioz

      145212




      145212






















          2 Answers
          2






          active

          oldest

          votes


















          1














          To add validation to your custom input component you should add the following to your providers:




          provide: NG_VALIDATORS,
          useExisting: forwardRef(() => InputTextComponent),
          multi: true



          You will have have to implement the default method, within your InputTextComponent:



          validate(control: AbstractControl): ValidationErrors | null 
          return null;



          If you correctly update a property within your component called value using the writeValue() method you implemented with your NG_VALUE_ACCESSOR and then ensure to call (you can do this by implementing a change event on your default input):



          this.propagateChange(this.value);


          Finally change your isRequired input to the default required property.



           @Input() required: boolean;


          Your NgModel should now correctly update.



          Edit: To avoid using required (however this is the correct way). Within the validation method place the following code:



          validate(control: AbstractControl): ValidationErrors | null 
          return this.isRequired && this.value.length === 0 : required: true : null;



          What is happening is when Angular runs its own validation it calls this method. When this method returns anything but null, the object is added to the errors property within the FormControl & NgModel.



          This is a huge topic and there are some great articles properly explaining it all. However, as asked, this should solve it.






          share|improve this answer

























          • Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

            – claudioz
            Nov 13 '18 at 16:21











          • Ok it works. But what if I wanted to keep the isRequired property?

            – claudioz
            Nov 13 '18 at 16:24












          • I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

            – claudioz
            Nov 13 '18 at 16:49











          • When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

            – Jmsdb
            Nov 13 '18 at 17:55


















          0














          You should check is form dirty and is it valid. So both needs to be true. Otherwise it shows it hasn't been changed.






          share|improve this answer






















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284663%2fangular-problem-with-form-validation-in-template-driven-form%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            To add validation to your custom input component you should add the following to your providers:




            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => InputTextComponent),
            multi: true



            You will have have to implement the default method, within your InputTextComponent:



            validate(control: AbstractControl): ValidationErrors | null 
            return null;



            If you correctly update a property within your component called value using the writeValue() method you implemented with your NG_VALUE_ACCESSOR and then ensure to call (you can do this by implementing a change event on your default input):



            this.propagateChange(this.value);


            Finally change your isRequired input to the default required property.



             @Input() required: boolean;


            Your NgModel should now correctly update.



            Edit: To avoid using required (however this is the correct way). Within the validation method place the following code:



            validate(control: AbstractControl): ValidationErrors | null 
            return this.isRequired && this.value.length === 0 : required: true : null;



            What is happening is when Angular runs its own validation it calls this method. When this method returns anything but null, the object is added to the errors property within the FormControl & NgModel.



            This is a huge topic and there are some great articles properly explaining it all. However, as asked, this should solve it.






            share|improve this answer

























            • Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

              – claudioz
              Nov 13 '18 at 16:21











            • Ok it works. But what if I wanted to keep the isRequired property?

              – claudioz
              Nov 13 '18 at 16:24












            • I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

              – claudioz
              Nov 13 '18 at 16:49











            • When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

              – Jmsdb
              Nov 13 '18 at 17:55















            1














            To add validation to your custom input component you should add the following to your providers:




            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => InputTextComponent),
            multi: true



            You will have have to implement the default method, within your InputTextComponent:



            validate(control: AbstractControl): ValidationErrors | null 
            return null;



            If you correctly update a property within your component called value using the writeValue() method you implemented with your NG_VALUE_ACCESSOR and then ensure to call (you can do this by implementing a change event on your default input):



            this.propagateChange(this.value);


            Finally change your isRequired input to the default required property.



             @Input() required: boolean;


            Your NgModel should now correctly update.



            Edit: To avoid using required (however this is the correct way). Within the validation method place the following code:



            validate(control: AbstractControl): ValidationErrors | null 
            return this.isRequired && this.value.length === 0 : required: true : null;



            What is happening is when Angular runs its own validation it calls this method. When this method returns anything but null, the object is added to the errors property within the FormControl & NgModel.



            This is a huge topic and there are some great articles properly explaining it all. However, as asked, this should solve it.






            share|improve this answer

























            • Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

              – claudioz
              Nov 13 '18 at 16:21











            • Ok it works. But what if I wanted to keep the isRequired property?

              – claudioz
              Nov 13 '18 at 16:24












            • I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

              – claudioz
              Nov 13 '18 at 16:49











            • When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

              – Jmsdb
              Nov 13 '18 at 17:55













            1












            1








            1







            To add validation to your custom input component you should add the following to your providers:




            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => InputTextComponent),
            multi: true



            You will have have to implement the default method, within your InputTextComponent:



            validate(control: AbstractControl): ValidationErrors | null 
            return null;



            If you correctly update a property within your component called value using the writeValue() method you implemented with your NG_VALUE_ACCESSOR and then ensure to call (you can do this by implementing a change event on your default input):



            this.propagateChange(this.value);


            Finally change your isRequired input to the default required property.



             @Input() required: boolean;


            Your NgModel should now correctly update.



            Edit: To avoid using required (however this is the correct way). Within the validation method place the following code:



            validate(control: AbstractControl): ValidationErrors | null 
            return this.isRequired && this.value.length === 0 : required: true : null;



            What is happening is when Angular runs its own validation it calls this method. When this method returns anything but null, the object is added to the errors property within the FormControl & NgModel.



            This is a huge topic and there are some great articles properly explaining it all. However, as asked, this should solve it.






            share|improve this answer















            To add validation to your custom input component you should add the following to your providers:




            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => InputTextComponent),
            multi: true



            You will have have to implement the default method, within your InputTextComponent:



            validate(control: AbstractControl): ValidationErrors | null 
            return null;



            If you correctly update a property within your component called value using the writeValue() method you implemented with your NG_VALUE_ACCESSOR and then ensure to call (you can do this by implementing a change event on your default input):



            this.propagateChange(this.value);


            Finally change your isRequired input to the default required property.



             @Input() required: boolean;


            Your NgModel should now correctly update.



            Edit: To avoid using required (however this is the correct way). Within the validation method place the following code:



            validate(control: AbstractControl): ValidationErrors | null 
            return this.isRequired && this.value.length === 0 : required: true : null;



            What is happening is when Angular runs its own validation it calls this method. When this method returns anything but null, the object is added to the errors property within the FormControl & NgModel.



            This is a huge topic and there are some great articles properly explaining it all. However, as asked, this should solve it.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 13 '18 at 18:00

























            answered Nov 13 '18 at 16:01









            JmsdbJmsdb

            44417




            44417












            • Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

              – claudioz
              Nov 13 '18 at 16:21











            • Ok it works. But what if I wanted to keep the isRequired property?

              – claudioz
              Nov 13 '18 at 16:24












            • I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

              – claudioz
              Nov 13 '18 at 16:49











            • When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

              – Jmsdb
              Nov 13 '18 at 17:55

















            • Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

              – claudioz
              Nov 13 '18 at 16:21











            • Ok it works. But what if I wanted to keep the isRequired property?

              – claudioz
              Nov 13 '18 at 16:24












            • I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

              – claudioz
              Nov 13 '18 at 16:49











            • When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

              – Jmsdb
              Nov 13 '18 at 17:55
















            Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

            – claudioz
            Nov 13 '18 at 16:21





            Thanks, I did everything, except the last step. Why I need to edit the input name (@Input() required: boolean;) and how is this reflected in the template of my custom component?

            – claudioz
            Nov 13 '18 at 16:21













            Ok it works. But what if I wanted to keep the isRequired property?

            – claudioz
            Nov 13 '18 at 16:24






            Ok it works. But what if I wanted to keep the isRequired property?

            – claudioz
            Nov 13 '18 at 16:24














            I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

            – claudioz
            Nov 13 '18 at 16:49





            I would like to avoid using the "required" property from the caller... I preder use the custom property "isRequired" from the caller

            – claudioz
            Nov 13 '18 at 16:49













            When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

            – Jmsdb
            Nov 13 '18 at 17:55





            When using NgModel and ControlValueAccessor, you are informing Angular that you will be treating this component as a default HTML input. You can use isRequired, however, your input element is not the input within the component but your InputTextComponent itself. I will update my answer to include a workaround, however, I would advise against it. That is why using require as you would with a real input is advised.

            – Jmsdb
            Nov 13 '18 at 17:55













            0














            You should check is form dirty and is it valid. So both needs to be true. Otherwise it shows it hasn't been changed.






            share|improve this answer



























              0














              You should check is form dirty and is it valid. So both needs to be true. Otherwise it shows it hasn't been changed.






              share|improve this answer

























                0












                0








                0







                You should check is form dirty and is it valid. So both needs to be true. Otherwise it shows it hasn't been changed.






                share|improve this answer













                You should check is form dirty and is it valid. So both needs to be true. Otherwise it shows it hasn't been changed.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 13 '18 at 15:58









                Slobodan GajićSlobodan Gajić

                104110




                104110



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284663%2fangular-problem-with-form-validation-in-template-driven-form%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Barbados

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3