web-dev-qa-db-ja.com

Angularフォーム検証とbootstrap=スタイル

私はAngularで非常に新しく、Angular and Bootstrap 4.を使用して登録フォームを作成しようとしています。

私が望む結果は、BootstrapのスタイルでAngularの検証を使用することです。より正確には、フォームを検証するとき、Angularはスタイル(ng -valid、ng-invalidなど)2つの異なる場所:入力要素とフォーム要素。

2つの質問:

1)Bootstrapは「ng- [in] valid」の代わりに「has-danger」と「has-success」を使用するため、angular =デフォルトのスタイルの代わりにこれらのスタイルを使用します。現在、bootstrapを拡張することを検討していますangularスタイル(@extend has-danger /成功)

2)Angularはスタイルを入力およびフォーム要素に適用しますが、bootstrapはフォームグループ要素でそれを期待します。angular入力要素の代わりにスタイルをそこに置きます(または両方ですか?)

私はリアクティブフォームを使用していますが、(テストされていない)ようなことを避けたいです:

<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>

これを達成する簡単な方法(冗長ではない)はありますか?

20
Rémi PIOTAIX

SASSを使用している場合は、すべてのCSSを書き換える必要なく、次のことができます。

.ng-touched.ng-invalid {
  @extend .is-invalid;
}

注:直接参照するのではなく、SASSビルドの一部としてbootstrapをインポートする必要があります。

SASSを使用していない場合は、こちらを参照してインストールしてください Angular CLI SASS options

23
Oliver

別のオプションはこのディレクティブです。

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がなくても動作し、コンパイルされた出力が小さくなる場合があります。

11
yankee

angular docsを見ている間に私に来た最良のアイデアは、ディレクティブを使用することです。私の実装はReactiveフォームでのみ動作し、スタイルを適用する要素にフォームコントロールが含まれる場合( bootstrapの場合)を使用する場合。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>
1
Rémi PIOTAIX