【问题标题】:Angular form validation and bootstrap stylesAngular 表单验证和引导样式
【发布时间】: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 中重新利用它。
  • 是的,但是当表单更改值时会出现问题,对吗?或者该函数应该返回一个可观察对象?
  • 不..没问题..每次更改都会调用您的函数。

标签: css forms angular twitter-bootstrap-4


【解决方案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>
    

    【讨论】:

      猜你喜欢
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      • 2012-12-30
      相关资源
      最近更新 更多