css - tag - Validación de formas angulares y estilos bootstrap.
image with text bootstrap 4 (3)
La mejor idea que se me ocurrió al mirar los documentos angulares es usar una directiva. Mi implementación solo funciona con formularios reactivos y si el elemento que desea aplicar el estilo contiene el control de formulario (que, si utiliza bootstrap, es el caso). Debe ser extendido para compatibilidad con select y textarea.
import { Directive, ElementRef, Input, OnInit } from ''@angular/core'';
import { FormControl, FormGroup } from ''@angular/forms''
@Directive({ selector: ''[formValidationStyle]'' })
export class FormValidationStyleDirective implements OnInit {
@Input(''formValidationStyle'') private formGroup: FormGroup;
private component: FormControl;
static VALID_STYLE: string = ''has-success'';
static INVALID_STYLE: string = ''has-danger'';
constructor(private el: ElementRef) { }
ngOnInit(): void {
let componentName: string;
let inputElement = this.el.nativeElement.querySelector(''input'');
if (inputElement) {
componentName = inputElement.getAttribute(''formControlName'');
}
if (!componentName) {
console.error(''FormValidationStyleDirective: Unable to get the control name. Is the formControlName attribute set correctly?'')
return;
}
let control = this.formGroup.get(componentName)
if (!(control instanceof FormControl)) {
console.error(`FormValidationStyleDirective: Unable to get the FormControl from the form and the control name: ${componentName}.`)
return;
}
this.component = control as FormControl;
this.component.statusChanges.subscribe((status) => {
this.onStatusChange(status);
});
this.onStatusChange(this.component.status);
}
onStatusChange(status: string): void {
let cl = this.el.nativeElement.classList;
if (status == ''VALID'') {
cl.add(FormValidationStyleDirective.VALID_STYLE)
cl.remove(FormValidationStyleDirective.INVALID_STYLE)
} else if (status == ''INVALID'') {
cl.add(FormValidationStyleDirective.INVALID_STYLE)
cl.remove(FormValidationStyleDirective.VALID_STYLE)
}
}
}
Ejemplo:
El componente:
@Component({
selector: ''security-register'',
templateUrl: ''./register.component.html''
})
export class RegisterComponent {
registerForm: FormGroup;
constructor(private http: Http, private fb: FormBuilder) {
this.registerForm = this.fb.group({
username: ['''', Validators.required]
});
}
}
Y su plantilla:
<form [formGroup]="registerForm" novalidate>
<div class="form-group" [formValidationStyle]="registerForm">
<label class="form-control-label" for="dbz-register-username">Login</label>
<input formControlName="username" type="text" class="form-control" id="dbz-register-username" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Register</button>
</div>
</form>
Soy bastante nuevo con Angular y estoy tratando de crear un formulario de registro utilizando Angular y Bootstrap 4.
El resultado que me gustaría es usar los estilos de Bootstrap con la validación de Angular. Más precisamente, al validar el formulario, Angular aplica estilos (ng-valid, ng-invalid, etc.) en dos lugares diferentes: el elemento de entrada y el elemento de formulario.
Dos preguntas:
1) Como Bootstrap usa ''has-danger'' y ''has-success'' en lugar de ''ng- [in] valid'', es posible configurar angular para usar estos estilos en lugar del predeterminado. Actualmente, estoy considerando la posibilidad de extender bootstrap al agregar los estilos angulares (con @extend has-danger / success)
2) Angular aplica el estilo a los elementos de entrada y de formulario, mientras que bootstrap lo espera en el elemento de grupo de formulario. ¿Es posible colocar el estilo angular allí en lugar del elemento de entrada (o ambos)?
Estoy usando formas reactivas y me gustaría evitar cosas como (no probadas):
<form>
<div class="form-group" [class.has-error]="!fg.get(''username'').valid" [class.has-success]="fg.get(''username'').valid">
<label>Username</label>
<input formControlName="username" type="text"/>
</div>
</form>
¿Hay una manera simple (no demasiado detallada) de lograr esto?
Otra opción es esta directiva:
import {Directive, HostBinding, Self} from ''@angular/core'';
import {NgControl} from ''@angular/forms'';
@Directive({
selector: ''[formControlName],[ngModel],[formControl]'',
})
export class BootstrapValidationCssDirective {
constructor(@Self() private cd: NgControl) {}
@HostBinding(''class.is-invalid'')
get isInvalid(): boolean {
const control = this.cd.control;
return control ? control.invalid && control.touched : false;
}
}
Simplemente agrega la clase is-invalid
a cada campo, si el campo es tocado o inválido. Básicamente se comporta de la misma manera que la solución SASS de Oliver, pero sigue sin SASS y también puede tener una salida compilada más pequeña.
Si está utilizando SASS, puede hacer lo siguiente sin tener que volver a escribir todo el css.
.ng-touched.ng-invalid {
@extend .is-invalid;
}
Nota: deberá importar bootstrap como parte de su compilación SASS en lugar de referenciarla directamente.
Si no está usando SASS, es bastante bueno instalarlo, vea aquí las opciones de Angular CLI SASS