Skip to content
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

Reactive forms validators are not represented in DOM (different behavior with the Template-driven forms) #43717

Open
spierala opened this issue Oct 5, 2021 · 3 comments
Assignees
Labels
area: forms design complexity: major P4 A relatively minor issue that is not relevant to core functions
Milestone

Comments

@spierala
Copy link

spierala commented Oct 5, 2021

Which @angular/* package(s) are the source of the bug?

forms

Is this a regression?

No

Description

The maxlength validator (https://angular.io/api/forms/MaxLengthValidator) works fine in Reactive Forms. However when using the maxlength attribute on a input in a Template Driven Form then the input is really restricted to the amount of characters which is specified via the maxlength attribute.

Expected behavior in Template Driven Form:
The input should not be restricted to the amount of characters. The form (or the formControl tied to the input) should just become invalid when the max amount of characters is exceeded.

It looks like the maxlength attribute is somehow conflicting with the Html input maxlength attribute (https://www.w3schools.com/tags/att_input_maxlength.asp)

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/angular-maxlength-validator-conflicts-with-html-maxlength?file=src/app/app.component.html

Please provide the exception or error you saw

No response

Please provide the environment you discovered this bug in

Angular 12.2.5 (see more info on the stackblitz example).

I saw the issue also in Angular 11.2.14


Tested in Chrome 94.0.4606.61

Anything else?

Actually I don't know if this is a regression.

@spierala spierala changed the title Angular maxlength validation conflicts with the HTML input "maxlength" attribute Template Driven Form: maxlength validation conflicts with the HTML input "maxlength" attribute Oct 5, 2021
@ngbot ngbot bot added this to the needsTriage milestone Oct 5, 2021
@AndrewKushnir AndrewKushnir self-assigned this Oct 12, 2021
@AndrewKushnir
Copy link
Contributor

@spierala thanks for reporting the issue.

I've looked at the repro and it seems like the template-driven forms behavior is actually more aligned with the native HTML behavior. I've created a small HTML page with an <input> element with the maxlength="5" attribute (see here) and the input is limited to 5 chars.

The difference in behavior is caused by the fact that the template-driven approach uses a directive that represents a validator and it also sets the maxlength attribute to the host <input> element (see here). In reactive forms, the validator function applied to the FormControl instance doesn't affect the <input> attributes, so a browser doesn't limit the input length.

In order to have the same behavior in reactive forms, you can use the [attr.maxlength]="5" for the <input> element (while also keeping the validator function):

<input type="text" formControlName="firstName" [attr.maxlength]="5" />

Thank you.

@AndrewKushnir AndrewKushnir added the P4 A relatively minor issue that is not relevant to core functions label Oct 27, 2021
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Oct 27, 2021
@AndrewKushnir AndrewKushnir changed the title Template Driven Form: maxlength validation conflicts with the HTML input "maxlength" attribute Reactive forms validators are not represented in DOM (different behavior with the Template-driven forms) Oct 27, 2021
@Totati
Copy link
Contributor

Totati commented Oct 12, 2022

@AndrewKushnir
Using ReactiveForms I have always though I have to set validators through the control's constructor or the functions provided by the AbstractControl. Managing validators for two related inputs, like a range of numbers, where the min control's changes should apply a Validators.min(min.value) validator to the max control and vice versa is pain as I have to remove the previous reference of the validator. (as I don't like to validate the FormGroup, cause writing out error messages under the control is messy)

I wanted to see how TemplateDrivenForms implements validators and as I looked at the selectors I saw that they support ReactiveForms directives too. I see that these validators are exported in both FormsModule.

Is it okay to use these directives for the ReactiveForms, I think I can cause the selectors are not made like this by mistake, but still, could not find any guides for this.
https://stackblitz.com/edit/angular-ivy-bta3ha?file=src%2Fapp%2Fapp.module.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts

@robmv
Copy link

robmv commented Apr 11, 2023

In order to have the same behavior in reactive forms, you can use the [attr.maxlength]="5" for the <input> element (while also keeping the validator function):

<input type="text" formControlName="firstName" [attr.maxlength]="5" />

I hope there was a way to not require this duplication, Maybe something like:

<input type="text" formControlName="firstName" ngValidatorAttrs />

Where ngValidatorAttrs (or a better name), will look at the control validators and set the correct attributes, This will require at least an event from FormControl signaling validator changes. Or extend the Validator interface with a method that return the attributes to add to an input field, like

getControlAttributes(type: 'input' | 'textarea'): Record<string, string>;

Maybe the type can be more open so it can be used on other kind of custom controls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: forms design complexity: major P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

No branches or pull requests

5 participants