I discovered today that validation is not always being displayed correctly in my application. In one particular example, angular will fail for required
if <option [ngValue]="null">
is selected; however, the browser sees <option value="0: null">
and does not fail on required
.
I'd like to switch to using Bootstrap's server-side validation classes to manually control when validation is displayed: https://getbootstrap.com/docs/4.0/components/forms/#server-side
Angular has ng-valid
and ng-invalid
and Bootstrap has is-valid
and is-invalid
. I don't want to copy the bootstrap CSS and just change the names. Rather, it'd be nice if there was a way to detect the angular classes and automatically add the bootstrap equivalent, something like this:
<select #s="ngModel"
id="s"
name="s"
[ngModel]="myModel"
required
class="form-control"
[class.is-valid]="s.valid"
[class.is-invalid]="s.invalid">
<option [ngValue]="null">Choose a value</option>
<option *ngFor="let item of items" [ngValue]="item.id">{{item.Name}}</option>
</select>
If there was a way to do this without needing to repeat those [class...]
attributes on every input, that'd be ideal.
I actually took a look at the Angular source code to see how they were universally applying ng-valid
and ng-invalid
. https://github.com/angular/angular/blob/4.4.5/packages/forms/src/directives/ng_control_status.ts#L38-L57
I ended up taking their code and creating my own directive that simply emits the bootstrap validation classes:
import { Directive, Self } from "@angular/core";
import { NgControl } from "@angular/forms";
const controlStatusHost = {
"[class.is-valid]": "ngClassValid",
"[class.is-invalid]": "ngClassInvalid"
};
@Directive({ selector: "[formControlName],[ngModel],[formControl]", host: controlStatusHost })
export class BSControlStatusDirective {
public constructor(@Self() private control: NgControl) {
}
get ngClassValid(): boolean {
if (this.control.control == null) {
return false;
}
return this.control.control.valid;
}
get ngClassInvalid(): boolean {
if (this.control.control == null) {
return false;
}
return this.control.control.invalid;;
}
}
It's the host
property on the decorator that's really doing all of the magic. Pretty neat!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With