Reputation: 2525
i have multiple input fields, adding and changing are working fine with that particular fieds, but when coming to error message section, if there is input field eror in one field it is shown in all other fields. But, i want error to display for that particular field.
HTML:
<md-card-content>
<ul class="listClass">
<li *ngFor="let media of videos; let i = index ">
<div>
<input type="text" name="{{media._id}}[i]" id="{{media._id}}[i]" class="form-control form-textbox input-text" [(ngModel)]="media.editText" #editText pattern="/^(ftp|http|https):\/\/[^ ]+$/" style="width: 58%;margin-left: 1%;">
</div>
<div *ngIf="errorMsg" style="color:red">
{{errorMsg}}
</div>
<p class="inputimg" style="float: right;display: inline-block">
<label *ngIf="media._id" class="img_change" (click)="change($event,media)" style="width: 100px;">Change Link</label>
<label *ngIf="!media._id" class="img_change" (click)="changetext($event,media)" >Add Link</label>
</p>
</li>
</ul>
</md-card-content>
TS:
change(event: any, media) {
if (media.editText.indexOf('https://www.youtube.com/embed') != -1) {
this.errorMsg="";
if (!media._id) {
var data:any = {
pin_id: this.pin_id,
media_type: "video",
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
})
} else if(media._id) {
var data:any = {
media_id: media._id,
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
this.loadMedias()
}, error => {
})
}
} else {
this.errorMsg = "Please enter valid URL";
}
}
here i havent used any form validations.
Upvotes: 1
Views: 1116
Reputation: 18647
Take a variable, which stores the id
of media
and display error message accordingly depending on the media ID.
this.errorDiv[media._id] = true;;
so that I can use
errorDiv
in *ngIf*ngIf="errorMsg[media._id] && (errorDiv[media._id])"
which checks the error message and specific Id and display error message accordinglyHTML:
<div>
<input type="text" name="{{media._id}}[i]" id="{{media._id}}[i]" class="form-control form-textbox input-text" [(ngModel)]="media.editText" #editText pattern="/^(ftp|http|https):\/\/[^ ]+$/" style="width: 58%;margin-left: 1%;">
</div>
<div *ngIf="errorMsg[media._id] && (errorDiv[media._id])" style="color:red">
{{errorMsg[media._id]}}
</div>
<p >
<label *ngIf="media._id" (click)="change($event,media)">Change Link</label>
<label *ngIf="!media._id" (click)="change($event,media)">Add Link</label>
</p>
Component:
public errorDiv = {};
public errorMsg = {};
change(event: any, media) {
if (media.editText.indexOf('https://www.youtube.com/embed') != -1) {
this.errorMsg[media._id] = "";
this.errorDiv[media._id] = "";
if (!media._id) {
var data:any = {
pin_id: this.pin_id,
media_type: "video",
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
})
} else if(media._id) {
var data:any = {
media_id: media._id,
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
this.loadMedias()
}, error => {
})
}
} else {
this.errorMsg[media._id] = "Please enter valid URL";
this.errorDiv[media._id] = true;
}
}
Upvotes: 3
Reputation: 1756
Try binding the error message to each media object separately:
HTML:
<md-card-content>
<ul class="listClass">
<li *ngFor="let media of videos; let i = index ">
<div>
<input type="text" name="{{media._id}}[i]" id="{{media._id}}[i]" class="form-control form-textbox input-text" [(ngModel)]="media.editText" #editText pattern="/^(ftp|http|https):\/\/[^ ]+$/" style="width: 58%;margin-left: 1%;">
</div>
<div *ngIf="media.errorMsg" style="color:red">
{{media.errorMsg}}
</div>
<p class="inputimg" style="float: right;display: inline-block">
<label *ngIf="media._id" class="img_change" (click)="change($event,media)" style="width: 100px;">Change Link</label>
<label *ngIf="!media._id" class="img_change" (click)="changetext($event,media)" >Add Link</label>
</p>
</li>
</ul>
</md-card-content>
TS:
change(event: any, media) {
if (media.editText.indexOf('https://www.youtube.com/embed') != -1) {
media.errorMsg="";
if (!media._id) {
var data:any = {
pin_id: this.pin_id,
media_type: "video",
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
})
} else if(media._id) {
var data:any = {
media_id: media._id,
image_path: media.editText
}
this.ApiService
.addLinkMedia(data)
.subscribe(
media => {
this.loadMedias()
}, error => {
})
}
} else {
media.errorMsg = "Please enter valid URL";
}
}
Upvotes: 1
Reputation: 1865
Best is you create a custom validator checking your input, you were pointed to the right direction but only very briefly. Create a new directive and provide it in your app module.
@Directive({
selector: '[appValidURL]',
providers: [{provide: NG_VALIDATORS, useExisting: URLValidatorDirective, multi: true}]
})
export class URLValidatorDirective implements Validator {
@Input('appValidURL') url: string;
validate(control: AbstractControl): {[key: string]: any} {
return this.url && this.url.startsWith("https://www.youtube.com/embed") ? {value: control.value}}: null;
}
}
Then in your input code use something like this.
<input type="text" name="videourl" id="videourl" class="form-control" required appValidURL [(ngModel)]="media.editText">
<div *ngIf="videourl.invalid && (videourl.dirty || videourl.touched)" class="alert alert-danger">
<div *ngIf="videourl.errors.required">
VideoURL is required!
</div>
<div *ngIf="videourl.errors.url">
It must be an embedded youtube video!
</div>
</div>
I have never used it like this, but it should work maybe with some minor tweeks.
Edit: This is only for a single input field, your can try tho to use your array names instead of "videourl", not sure how this works out.
Upvotes: 0
Reputation: 6983
You can do soething like this. Without doing anything in ts file. You can validate and show validation messages just using form controls.
<input id="name" name="name" class="form-control"
required minlength="4" appForbiddenName="bob"
[(ngModel)]="hero.name" #name="ngModel" >
<div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required.
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>
Taken from angular official doc
Upvotes: 0
Reputation: 148
See the code below and you will realize your mistake. You must add condition that is for the current input only.
<div [ngClass]="{ 'has-error': form.submitted && !username.valid }">
<label for="firstName">First Name</label>
<input type="text" name="firstName" [(ngModel)]="model.firstName" #firstName="ngModel" required />
<div *ngIf="form.submitted && !firstName.valid">First Name is required </div>
</div>
<div [ngClass]="{ 'has-error': form.submitted && !username.valid }">
<label for="lastName">Last Name</label>
<input type="text" name="lastName" [(ngModel)]="model.lastName" #lastName="ngModel" required />
<div *ngIf="form.submitted && !lastName.valid" >Last Name is required</div>
</div>
Upvotes: 0