私は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>
これを達成する簡単な方法(冗長ではない)はありますか?
SASSを使用している場合は、すべてのCSSを書き換える必要なく、次のことができます。
.ng-touched.ng-invalid {
@extend .is-invalid;
}
注:直接参照するのではなく、SASSビルドの一部としてbootstrapをインポートする必要があります。
SASSを使用していない場合は、こちらを参照してインストールしてください Angular CLI SASS options
別のオプションはこのディレクティブです。
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 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>