Angular 表单验证和引导样式
Posted
技术标签:
【中文标题】Angular 表单验证和引导样式【英文标题】:Angular form validation and bootstrap styles 【发布时间】:2017-10-22 11:40:25 【问题描述】:我是 Angular 的新手,我正在尝试使用 Angular 和 Bootstrap 4 创建一个注册表单。
我想要的结果是使用 Bootstrap 的样式和 Angular 的验证。 更准确地说,在验证表单时,Angular 在两个不同的地方应用样式(ng-valid、ng-invalid 等):输入元素和表单元素。
两个问题:
1) 由于 Bootstrap 使用 'has-danger' 和 'has-success' 而不是 'ng-[in]valid',是否可以将 angular 配置为使用这些样式而不是默认样式。目前,我正在考虑通过添加角度样式来扩展引导程序(使用@extend has-danger/success)
2) Angular 将样式应用于 input 和 form 元素,而 bootstrap 期望它应用于 form-group 元素。是否可以将样式放在那里而不是输入元素(或两者兼而有之?)
我正在使用响应式表单,我想避免类似(未测试)之类的事情:
<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>
有没有一种简单的方法(不太冗长)来实现这一点?
【问题讨论】:
您可以使用[ngClass]="getKlass('myControlName')"
并在您的组件中创建一个方法...类似于getKlass(controlName: string)
并从中执行您的逻辑返回类,所以您可以在您的所有inputs
中重新利用它。
是的,但是当表单更改值时会出现问题,对吗?或者该函数应该返回一个可观察对象?
不..没问题..每次更改都会调用您的函数。
【参考方案1】:
另一个选项是这个指令:
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;
如果字段被触摸或无效,它只是将is-invalid
类添加到每个字段。它的行为基本上与 Oliver 的 SASS 解决方案相同,但在没有 SASS 的情况下也能正常工作,而且编译后的输出也可能更小。
【讨论】:
这对我使用 Angular 7 和 Bootstrap 4 有用。谢谢! 我无法让它与 Angular 7 和 BS4 一起使用。我的控件上的标记是<input type="text" formControlName="manufacturer">
,即使存在ng-invalid
和ng-touched
,也没有添加is-invalid
类。
@JamieIde:这表明该指令甚至没有加载。您可能缺少一些导入语句。然而,这将证明一个单独的问题......
@yankee 谢谢,我最终得到了这个工作。我认为你是对的,我没有导入权。
如果你能添加一个如何使用这个指令的例子会很棒【参考方案2】:
如果您使用的是 SASS,则无需重写所有 css 即可执行以下操作。
.ng-touched.ng-invalid
@extend .is-invalid;
注意:您需要将引导程序作为 SASS 构建的一部分导入,而不是直接引用它。
如果您不使用 SASS,安装起来很漂亮,请参见此处 Angular CLI SASS options
【讨论】:
【参考方案3】:在查看 Angular 文档时,我想到的最佳想法是使用指令。 我的实现仅适用于反应式表单,并且如果您要应用样式的元素包含表单控件(如果您使用引导程序,就是这种情况)。应该扩展以兼容 select 和 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)
例子:
组件:
@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]
);
及其模板:
<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>
【讨论】:
以上是关于Angular 表单验证和引导样式的主要内容,如果未能解决你的问题,请参考以下文章