Reputation: 7037
This StackBlitz, I'd like to learn how to:
minLength(4)
Upvotes: 0
Views: 889
Reputation: 57939
Jeb, you has a type error when defined the FormGroup, see that if we has two or more validators you pass an array of validators
this.myForm = this.fb.group({
uname: ['', [Validators.required, Validators.minLength(4)]] //<--is an array
});
About the class we can has in styles.css some like
input.ng-invalid.ng-touched { //<--is necesary the "input", else a custom form
//control will be bordered too
border: 1px solid red;
}
If we want only when "submited" we can use, e.g.
input.ng-invalid.ng-touched.submitted {
border: 1px solid red;
}
And use a variable in our ts
submitted :boolean=false;
And our input add [class.submitted]
<input [class.submitted]="submitted" type="text" formControlName="uname" ..>
About the repeater there're several aproach. One can be create a custom-error, one component like
@Component({
selector: 'custom-error',
template: `
<small class="error" *ngIf="isInvalid" >
<ng-content></ng-content>
</small>
`,
styles:[`
.error{
color:red
}
`]
})
export class ErrorComponent {
@Input() submitted:boolean=true;
get isInvalid() {
const control = this.form.form.get(this.controlName);
return this.submitted && control.touched && control.invalid && (this.error ? control.errors[this.error] : true);
}
constructor(@Optional() @Host() private form: FormGroupDirective,
@Attribute("controlName") private controlName,
@Attribute("error") private error) { }
}
Allow us write some like
//if we want not wait to submitted and a unique Validators
<custom-error controlName="uname" >Required</custom-error>
//if there're an unique Validators
<custom-error [submitted]="submitted" controlName="uname" >Required</custom-error>
//if we severals validators
<custom-error [submitted]="submitted" error="required" controlName="uname" >Required</custom-error>
We can imagine another kinds of "custom-errors" that only show one error
//this "defaultErrors should be in a external file and completed with other erros
//this allow us reemplace case we want "localize" our app
export const defaultErrors = {
required: (error) => `This field is required`,
minlength: ({ requiredLength, actualLength }) => `Expect ${requiredLength} but got ${actualLength}`,
default:'field invalid' //<--add a string with the default error
}
@Component({
selector: 'custom-error-unique',
template: `
<small class="error" *ngIf="hasError" >
{{hasError}}
</small>
`,
styles:[`
.error{
color:red
}
`]
})
export class ErrorUniqueComponent {
errors=defaultErrors
@Input() submitted:boolean=true;
@Input('errors') set _(value)
{
this.errors={...defaultErrors,...value}
}
@Input() submitted:boolean=true;
@Input() errors:any=defaultErrors;
get hasError() {
const control = this.form.form.get(this.controlName);
const invalid=this.submitted && control.touched && control.invalid
let error=null
if (invalid)
{
Object.keys(this.errors).forEach(x=>{
if (control.errors[x] && !error)
{
error=this.errors[x](control.errors[x])
}
})
if (!error)
error=this.defaultErrors.default
}
return error
}
constructor(@Optional() @Host() private form: FormGroupDirective,
@Attribute("controlName") private controlName,
@Attribute("error") private error) { }
}
In this stackblitz thre're the two custom-errors components
Even we can imagine that appears magically. Well, Netanel Basal think about it before us: see this great entry blog
Upvotes: 1
Reputation: 6152
You can add this style to styles.css
.has-error {
border: 1px solid red;
}
then something like this to input:
<input type="text" formControlName="uname" placeholder="Enter Name..." [ngClass]="{ 'has-error': myForm.controls?.uname.errors && (myForm.controls?.uname.dirty || myForm.controls?.uname.touched) }">
Upvotes: 1