I am trying to display a mat error depending on the type of validator met. One validator being required (will display if field is touched and left empty) and another maxLength (which will display if the field has been touched and over 20 characters have been entered) - each scenario should display a different mat error message.
Firstly, I have my form group itself (in the component.ts), with the form control and its respective validators:
this.addBranchDetailsForm = this.fb.group({
branchName: ['', Validators.required, Validators.maxLength(20)]
});
Secondly, inside the component.html file, I have the Mat Form Field which makes reference to the aforementioned form group and control:
<form [formGroup]="addBranchDetailsForm">
<mat-form-field hintLabel="Enter the new branch name">
<mat-label>Branch Name</mat-label>
<input matInput #input maxlength="30" formControlName="branchName">
<mat-hint align="end">{{input.value?.length || 0}}/30</mat-hint>
<mat-error *ngIf="branchName">{{formOneErrorMessage()}}</mat-error>
</mat-form-field>
</form>
And then lastly, i have the "formOneErrorMessage" method in my component.ts file, which is responsible for the conditional error handling:
formOneErrorMessage() {
if (this.addBranchDetailsForm.get('branchName')?.hasError('required')) {
return 'Enter new branch name';
}
else if (this.addBranchDetailsForm.get('branchName')?.hasError('maxLength')) {
return 'The new branch name may not be more then 20 characters';
}
}
The issues I have are as follows:
Within the component.html file, with regards to the reference made to the "branchName" within the ngIf of the mat error, it says "Property 'branchName' does not exist on type 'CreateBranchComponent'.ngtsc(2339)".
Similarly, with reference made to the "formOneErrorMessage()" method within the mat error itself, it says "Property 'formOneErrorMessage' does not exist on type 'CreateBranchComponent'.ngtsc(2339)".
Lastly. Looking at the "formOneErrorMessage()" method within the component.ts file, the returns are throwing errors as well, stating: "Type 'string' is not assignable to type 'void'.ts(2322):"...
My suspicion is that I am not referencing the branchName form control correctly in the "formOneErrorMessage()" method.. Although, otherwise I am quite unsure.
I ended up using the following (in component.ts):
public errorHandling = (control: string, error: string) => {
return this.addBranchDetailsForm.controls[control].hasError(error);
}
And then within the component.html:
<mat-form-field hintLabel="Enter the new branch name">
<mat-label>Branch Name</mat-label>
<input matInput #input maxlength="30" formControlName="branchName">
<mat-hint align="end">{{input.value?.length || 0}}/30</mat-hint>
<mat-error *ngIf="errorHandling('branchName','required')">
Branch Name may not be empty
</mat-error>
<mat-error *ngIf="errorHandling('branchName','maxlength')">
Branch Name may not be more than 20 characters
</mat-error>
</mat-form-field>
Related
I have the following HTML Angular tags, which need to trigger a validation error when there is a negative value entered in any of the groups of textboxes (dynamic array).
<tr *ngFor="let order of configWT.get('wtFormArray').controls; let i =index" formArrayName ="wtFormArray">
<input natinput type ="number" [formControlName]="i" id="wtage" ngModelChange="updateWTage(i)" required>
ngOnInit
ngOnInit():void
{
this.configWT = this.formBuilder.group({
wtFormArray: new FormArray(['',[Validators.min(0)]])
}
Here is the error condition which is working for required validation, but not working for min validation.
Working
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('required'))"
error test
<nat-error>
Not Working
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('min')"
error test
<nat-error>
Here is the DOM
I am feeling like I am comparing min value with an array which may be causing this problem? please help!
I think, you should use minlength for minimum validation, it will be easier, because for new FormArray it's not correct to add validation in such way
<input natinput type ="number"
[formControlName]="i"
id="wtage"
ngModelChange="updateWTage(i)"
required
minlength="4">
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('minlength')">
error test
<nat-error>
I'm trying to implement a new Angular component with template-driven form validation. I have been following the documentation here, but cannot seem to replicate the results. Specifically, the div showing the error just doesn't appear when the input is invalid.
Here is the source code for context:
Template:
<mat-form-field class="input">
<input matInput matTooltip="Float value between 0.0 and 1.0"
type="number"
placeholder="Confidence"
min="0.0"
max="1.0"
[(ngModel)]="confidence"
#value="ngModel">
<mat-error *ngIf="value.invalid && (value.errors.min || value.errors.max)">
Confidence must be an decimal value between 0.0 and 1.0.
</mat-error>
</mat-form-field>
Relevant component code:
metadata = {confidence: 0.0, ...};
get confidence(): number {
return this.metadata.confidence;
}
set confidence(confidenceIn: number) {
this.metadata.confidence = confidenceIn;
}
My understanding is that the line #value="ngModel" makes a local variable value containing the value of the input element it was declared on, which then allows me to reference value as in the following *ngIf directive to check for errors.
However, the mat-error element never shows up when the input value is out of range (less than 0, more than 1), so my understanding is probably wrong and/or I've implemented this incorrectly.
Any explanations would be greatly appreciated!
I have a data object obj with multiple parameters:
export interface obj {
param1: number;
param2: number;
param3: number;
}
I would like to dynamically add mat-grid-tiles with mat-form-fields displaying their value.
I do this by creating an array of the parameter names:
params = ['param1', 'param2', 'param3']
Then, in my HTML code, I use my mat-grid-tiles with *ngFor on the parameter names and then assign the reference to my obj in [ngModel]:
<mat-grid-tile [colspan]=1 *ngFor="let param of params">
<mat-form-field>
<input matInput [ngModel]="coilData[params]" readonly>
</mat-form-field>
</mat-grid-tile>
It works! However, because my obj is initially null until an API call is made, it seems to throw hundreds of null errors like so:
ERROR TypeError: Cannot read property 'param1' of null
I realized that I can just use the Elvis Operator: ?, however I can not seem to figure out how to use this on [ngModel] when I am dynamically assigning parameter names to it like this: [ngModel]="obj[param]" instead of the usual [ngModel]="obj?.param1.
Is it possible to use the Elvis Operator when dynamically applying parameter names to ngModel?
Ended up taking Heretic Monkey's suggestion and used obj ? obj[param] : null instead which ended up working for me.
Try
< ng-container *ngIf="coilData" >
<mat-grid-tile [colspan]=1 *ngFor="let param of params">
<mat-form-field>
<input matInput [ngModel]="coilData[params]" readonly>
</mat-form-field>
</mat-grid-tile>
< ng-container />
I am trying to replace boostrap's combobox with material's autocomplete without refactoring much of the previous code;
This is what the html of the new material autocomplete looks like :
<input matInput placeholder="New room" aria-label="Newsroom Source" [matAutocomplete]="autoGroup" [formControl]="newsRoomCtrl" [value] = 'selectedNewsFeed.sourceName'>
<mat-autocomplete #autoGroup="matAutocomplete" (optionSelected)='onNewsRoomSelect($event.value)' >
<mat-option *ngFor="let newsroomsource of filteredNewsRoomSources | async" [value]="newsroomsource" [attr.data-row]="newsroomsource">
<span>{{ newsroomsource.sourceName }}</span> |
<small>Type: {{ newsroomsource.sourceType }}</small>
</mat-option>
</mat-autocomplete>
On '(optionSelected)' event I call the function onNewsRoomSelect(selectedNewsRoom: NewsRoomSource) by passing the selected newsroomsource as an object using event.value
This works fine ,the problem though is that the value of the input becomes an object in this case and NewsRoomSource object, and this is what I see in the input after the selection is made;
Selecting:
After selection :
Now I understand why this happens as I set [value] of the mat-input tag to an object i.e. newsroomsource, but I don't know how else I can reference the selected object if I don't do this.
As you can see in the code I tried using data-attribute but wasn't sure how exactly I can use it in this case
In this case newsRoomCtrl has the reference of the selected object try by printing this variable console.log(newsRoomCtrl);
Finally I think it is going to be like that, take a look to the object structure to be sure.
<input matInput placeholder="New room" aria-label="Newsroom Source" [matAutocomplete]="autoGroup"
[formControl]="newsRoomCtrl" [value] = 'newsRoomCtrl.value.sourceName'>
<paper-input
id="server"
floatinglabel=""
label="Server Address"
value=""
required
type="URL">
</paper-input>
the example above worked until the latest polymer update now even the required attribute does nothing. was there some change to core-input that i am missing in documentation? all my inputs with patterns, numbers, urls, or emails nothing causes it to get the invalid class.
<paper-input-decorator
id="address"
labelVisible
floatinglabel
error="URL Required"
label="Server Address">
<input is="core-input" type="URL" id="server" required>
</paper-input-decorator>
above is the updated markup for checking input of url. before the changes the input had invalid by default cause the field was required and updated as you type.
with the new changes you have to call a function to get the input to return the invalid class. (you could put a event listener on the input and run that function every time the input is updated. but i only check on attempted submission) to check i put all the inputs i want to check in a container (a div with a id) then when user click to submit i run the function below.
validate: function (id) {
'use strict';
var $d = document.getElementById(id).querySelectorAll('paper-input-decorator');
Array.prototype.forEach.call($d, function(d) {
d.isInvalid = !d.querySelector('input').validity.valid;
});
}
and pass in the id of the input container. validate(id);
that will cause the input to display the invalid class if input doesn't meet type / pattern requirement. you can then check for invalid class in the same method as before.
invalid = document.querySelector("#address").classList.contains("invalid");
outside a custom element or
invalid = this.$.address.classList.contains("invalid");
inside custom element
then some logic to check for invalid class before running the save function
if (!invalid) {
save();
}
also keep in mind that the decorator and input both have a id. the id on the decorator is used to check for validity while the id on the input is there for getting the value from the committedValue attribute.
info above is for the master branch pulled after 10 - 16 - 14