I'm trying to have inputs with a regex requirement in a ngFor loop but am not seeing the error message as expected when I put something that doesn't match the required pattern.
"Test" is never hidden and <div *ngIf="id?.hasError('pattern')"> never shows, even when I enter the wrong pattern. I can see that the input fails because I'm using Material Design and the color of the line underlining the input changes to red but I do not see any changes in regards to the error messages.
Here is my code at the moment:
(The keys pipe I have is a custom pipe because item is an object made of objects, so that breaks down the contained objects into key/value pairs.)
<div *ngFor="let item of items | keys">
<md-input-container>
<input
mdInput
placeholder={{item.placeholder}}
name={{item.name}}
pattern="\d{7}"
[(ngModel)]="item.currentValue"
#id="ngModel"
>
</md-input-container>
<div
[hidden]="id?.valid || id?.pristine"
>
<p>Test</p>
<div *ngIf="id?.hasError('pattern')">
Pattern should be xxxxxxx
</div>
</div>
</div>
Try by changing name={{item.name}} to name="id".
Try it in next way:
<div *ngFor="let item of items | keys">
<md-input-container>
<input
mdInput
placeholder={{item.placeholder}}
name={{item.name}}
pattern="\d{7}"
[(ngModel)]="item.currentValue"
#id="ngModel"
>
</md-input-container>
<div [hidden]="!displayValid(id)">
<p>Test</p>
Pattern should be xxxxxxx
</div>
</div>
And this fun in .ts file of component:
displayValid(inputRef: any): boolean {
let errors: any = inputRef.errors;
return errors && errors.pattern;
}
Related
I have a list of the mat-slide-toggle. At a time only one slider will remain enabled and other slider will remain disabled.
Now while clicking on that enabled slider it's value will be changed and simultaneously other list of slider will be get enabled for selection and once the one slider will be get selected then other will be get disabled.
So, in short from the whole array only one mat-slide-toggle should be selected and other will be disabled simultaneously.
For that I have make the code as below.
<form [formGroup]="selectionForm">
<div class="row">
<div formArrayName="selectOption">
<div *ngFor="let select of selectionForm['controls'].selectOption['controls']; let i=index">
<div [formGroupName]="i">
<div formArrayName="selectionList">
<div *ngFor="let obj of select.controls['selectList'].controls; let j = index">
<div [formGroupName]="j">
<mat-slide-toggle formControlName="isSelected"" (change)="changeSelection($event)" disabled="slidValue || obj.isSelected === false"> Is selected? </mat-slide-toggle>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
In TS code:
public slidValue;
changeSelection(event) {
this.slidValue = false
}
Sample JSON Response
StackBlitz demo.
Eg: On load of the page:
Now when change the slide toggle all other options value not getting change from false to true for selection.
I would like to create dynamically 3 input tags in Angular 6 to not copy/paste html code because that input elements have similar html and functionality.
For this purpose I created an array "reusableItems" inside component and initialize it :
let numberOfInputElements = 3;
for (let i = 0; i < numberOfInputElements; i++) {
this.reusableItems.push({
answer: 'Answer ' + (i +1),
passwordRecoveryAnswer: this.user['passwordRecoveryAnswer' + (i + 1)]
});
}
Then I put code inside my html :
<div *ngFor="let item of dropDownDataManagerService.reusableItems" >
<li class="col-xs-12 pl-lg pr0 pv-sm bd1-bottom">
<div class="col-xs-4 ph0 pt"> {{item.answerTitle}}</div>
<div class="col-xs-8">
<input type="text" name={{item.answer}} ref-{{item.answer}}="ngModel" class="col-sm-12 k-textbox ph0"
[(ngModel)]=item.passwordRecoveryAnswer
[pattern]="[a-z]"
required autocomplete="off"/>
</div>
</li>
</div>
It seems works fine but then I need to add error messages when these fields will be empty and not match to pattern. Something like :
<div *ngIf="__{{item.answer}}__.errors?.required ">
{{'Please provide an answer' | translate}}
</div>
<div *ngIf="__{{item.answer}}__.errors?.pattern">
{{'Pattern is not match'}}
</div>
I don't know what should i put inside ngIf condition.
How can I do it if my template reference variables are comes from array?
Is anyone have ideas?
Thanks
Angular creates unique template reference variable for each embedded template so that you can use the same template reference variable name inside ngFor loop:
<div *ngFor="let item of reusableItems">
<li class="col-xs-12 pl-lg pr0 pv-sm bd1-bottom">
<div class="col-xs-4 ph0 pt"> {{item.answerTitle}}</div>
<div class="col-xs-8">
<input type="text" name={{item.answer}} ref-answer="ngModel" class="col-sm-12 k-textbox ph0" [(ngModel)]="item.passwordRecoveryAnswer"
[pattern]="'[a-z]'" required autocomplete="off" />
<div *ngIf="answer.errors?.required">
{{'Please provide an answer'}}
</div>
<div *ngIf="answer.errors?.pattern">
{{'Pattern is not match'}}
</div>
</div>
</li>
</div>
In the code above I use the same name for each input in array
ref-answer="ngModel" // or you can also use #answer="ngModel
I have a problem with sending values from one component to other. I've got 2 components: report-form and comment-form. Report form have an array of comments. It also show list of comment and button for each of them. After clicking a button It should load modal form with #Input property commentIndex. Problem is that report-form component don't send only(!) first value of array to comment-form. I don't have idea why :/.
Here's some code:
Part of report-form.html:
<div class="form-group row">
<div class="col-md-12 alert alert-dark">Komentarze:</div>
<div class="col-md-12" *ngFor="let comment of comments">{{ comment.content }}
<app-comment-form [commentIndex]="comments.indexOf(comment)"></app-comment-form>
</div>
<br>
<app-comment-form></app-comment-form>
</div>
If I log it on console in comment-form I've got 1,2 in 3 elements array but where's 0?!
You can use index provided by the *ngFor directly.
<div class="form-group row">
<div class="col-md-12 alert alert-dark">Komentarze:</div>
<div class="col-md-12" *ngFor="let comment of comments; let i = index">{{ comment.content }}
<app-comment-form [commentIndex]="i"></app-comment-form>
</div>
<br>
<app-comment-form></app-comment-form>
</div>
This index will start from 0.
I'm trying to make some textboxes appear everytime a user clicks a button.
i'm doing this with ngFor.
For some reason, the ngFor won't iterate.
I've tried using slice to change the array reference, but still, the text boxes won't appear.
Any idea what i'm doing wrong??
Below are the HTML and component codes.
Thanks!!!
export class semesterComponent {
subjectsNames = [];
addSubject(subjectName: string) {
if (subjectName) {
this.subjectsNames.push(subjectName);
this.subjectsNames.slice();
console.log(subjectName);
console.log(this.subjectsNames);
}
};
<div class="semester-div">
<ul>
<li ngFor="let subject of subjectsNames">
<span>
<input #subjectName type="text" />
<input id = "subjectGrade" type = "number"/>
<input id = "subjectWeight" type = "number"/>
</span>
</li>
</ul>
<br>
<button (click)="addSubject(subjectName.value)">add</button>
<br>
</div>
You are missing the * in *ngFor
<li *ngFor="let subject of subjectsNames">
The way you have your controls written subjectName does not exist because the array is empty and therefore the *ngFor does not render it. Clicking the Add button results in a exception that the value doesn't exist on undefined where undefined is really subjectName.
Moving it outside of the *ngFor will make things work:
<input #subjectName type="text" />
<ul>
<li *ngFor="let subject of subjectsNames">
<span>
{{subject}}
<input id="subjectGrade" type="number"/>
<input id="subjectWeight" type="number"/>
</span>
</li>
</ul>
I suspect you also want to further bind the data as you iterate over the subject names but that's outside the scope of the question.
Here's a plunker: http://plnkr.co/edit/HVS0QkcLw6oaR4dVzt8p?p=preview
First, you are missing * in *ngFor.
Second put out
<input #subjectName type="text" />
from ngFor, should work.
I am generating dynamic form based on angularjs and semantic-ui, the problem that anglers have a problem when parsing some French letter for example "français"
Lexer Error: Unexpected next character at columns 29-29 [ç] in expression [{'error' : (categoryForm.Français.$dirty && categoryForm.Français.$invalid)}].
the form was dynamically generated based on data loaded from server side :
<div class="two fields" data-ng-repeat="lang in category.languages">
<div class="field width_80"
data-ng-class="{'error' : (categoryForm.{{lang.languageName}}.$dirty && categoryForm.{{lang.languageName}}.$invalid)}">
<label data-ng-bind="lang.languageName"></label>
<div class="ui labeled icon left input">
<input type="text" name="{{lang.languageName}}" data-ng-model="lang.name" required
data-ng-minlength="3"/>
<i class="font icon"
data-ng-class="{'red' : (categoryForm.{{lang.languageName}}.$dirty && categoryForm.{{lang.languageName}}.$invalid)}"></i>
</div>
<div class="ui red pointing label transition"
data-ng-show="categoryForm.{{lang.languageName}}.$dirty && categoryForm.{{lang.languageName}}.$error.required">
{{'error.required' | i18n }}
</div>
<div class="ui red pointing label transition"
data-ng-show="categoryForm.{{lang.languageName}}.$dirty && categoryForm.{{lang.languageName}}.$error.minlength">
{{'error.minlength' | i18n }} 3 {{'error.digit' | i18n}}s
</div>
</div> ...
how could I escape some letter in dynamic generation
I have found the answer, first of all the problem of "Français" was resolve using brackets annotation categoryForm [Lang. languageName]. $invalid instead of categoryForm. {{Lang. languageName}}.$invalid thanks to Nikos Paraskevopoulos.
the second problem was the dynamic generation of input name that I have the answer she dynamic input name generatrion