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 一起使用。我的控件上的标记是&lt;input type="text" formControlName="manufacturer"&gt;,即使存在ng-invalidng-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 表单验证和引导样式的主要内容,如果未能解决你的问题,请参考以下文章

angular12表单错误提示不显示边框

怎么消除angular的表单验证

引导表单验证 - 使用点击事件验证表单

带密码确认的引导 4 验证并禁用提交,直到表单验证(注册表单)

django登录表单和表单验证在引导模式中使用ajax

Angular 4 表单验证和错误消息