複数のフォームフィールドに依存するAngular2バリデーター


118

複数の値を使用してフィールドが有効かどうかを判断できるバリデーターを作成することはできますか?

たとえば、顧客の希望する連絡方法が電子メールの場合、電子メールフィールドは必須です。

ありがとう。


サンプルコードで更新...


    import {Component, View} from 'angular2/angular2';
    import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';

    @Component({
        selector: 'customer-basic',
        viewInjector: [FormBuilder]
    })
    @View({
        templateUrl: 'app/components/customerBasic/customerBasic.html',
        directives: [formDirectives]
    })
    export class CustomerBasic {
        customerForm: ControlGroup;

        constructor(builder: FormBuilder) {
            this.customerForm = builder.group({
                firstname: [''],
                lastname: [''],
                validateZip: ['yes'],
                zipcode: ['', this.zipCodeValidator] 
                // I only want to validate using the function below if the validateZip control is set to 'yes'
            });
        }

        zipCodeValidator(control) {
            if (!control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)) {
                return { invalidZipCode: true };
            }
        }

    }

はい。また、コードをご提示いただければ、具体的な回答を追加することもできます。
ミケレム2015

基本的な例を追加しました。サンプルコードで、前のvalidateZipコントロールに「yes」が含まれている場合にのみ郵便番号を検証するにはどうすればよいですか?
Simon

サイモン、あなたの質問へ答えを宣伝しみませんか?
superjos 16

6
わかりました。この質問の将来の訪問者を多くの不満から救うために、このNPMパッケージを使用することを強くお勧めします:npmjs.com/package/ng2-validation 組み込みequalequalToメソッド、そして優れたドキュメントがあります!
ミケランジェロ

回答:


147

他の人が投稿した方法を繰り返すと、これは私が作成してきた方法です FormGroup複数のグループを含まないバリデーターをです。

この例では、passwordおよびconfirmPasswordフィールドのキー名を指定するだけです。

// Example use of FormBuilder, FormGroups, and FormControls
this.registrationForm = fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Validatorsがパラメータを取得するためには、をfunctiona FormGroupまたはFormControlパラメータとして返す必要があります。この場合、私はを検証していFormGroupます。

function matchingPasswords(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirmPassword = group.controls[confirmPasswordKey];

    if (password.value !== confirmPassword.value) {
      return {
        mismatchedPasswords: true
      };
    }
  }
}

技術的には、キーがわかっていれば2つの値を検証できたかもしれませんがValidators、それらが返すエラーと同じ名前を付けることを好みます。関数は、返されたエラーのキー名を表す3番目のパラメーターを取るように変更できます。

2016年12月6日更新(v2.2.4)

完全な例:https : //embed.plnkr.co/ukwCXm/


@Dave << 複数のグループを含まない >>実際に<<複数のグループを含む>>という意味ですか?ありがとう
superjos 2016年

パスワードがAngular 2 RC.1と一致する場合、これは警告マークアップを削除しないようです
datatype_void

「ControlGroups」は2.0には存在しないようです。私は「FormGroup」を使用しました
Stephen

@superjos私はそう言うつもりでした。一部の開発者は、全体FormGroupを配置するのValidatorではなく、ネストされたマルチフィールド検証を処理することを選択します。
cyber_dave 16

1
パスワード、confirmPassword、電子メール、および電子メールの確認がある場合はどうなりますか? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] 私はこれを試しましたが、うまくいきません。助言がありますか ?@Dave
Sharan Ainapurapu 2017

51

デイブの答えは非常に役に立ちました。ただし、若干の変更は一部の人々を助けるかもしれません。

Controlフィールドにエラーを追加する必要がある場合は、フォームとバリデーターの実際の構成を維持できます。

// Example use of FormBuilder, ControlGroups, and Controls
this.registrationForm= fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

でエラーを設定する代わりControlGroupに、実際のフィールドで次のように設定します。

function matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: ControlGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

6
ブランチで使用passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))してelse、変更passwordInputによりデータが有効になったときに正しく更新されるようにします。
andraaspar

@andraaspar試してみましたが、エラーが発生しましたTypeError: passwordConfirmationInput.validator is not a function。これは、Validators.requiredを使用してFormControlを明示的に作成しなかったためです。バリデーターを空白のままにして、代わりに入力で「必須」属性を使用しました。
beardedlinuxgeek

6
これは役に立ちましたが、角度のドキュメントにはの戻り値の型があり{[key: string]: any}、それsetErrors(...)が返されないことに気付きました(もう?)。またsetErrors(...)、すでに存在するすべてのエラーを上書きするため、次のように現在のエラーオブジェクトに追加します:let errors = formGroup.controls[passwordConfirmationKey].errors;and if(!errors) errors={};and errors['notEquivalent'] = true;andformGroup.controls[dateControlFirst].setErrors(errors);
Stephen

32

複数のフォームフィールドにバリデーターを実装する場合、各フォームコントロールが更新されるときにバリデーターが再評価されることを確認する必要があります。ほとんどの例はそのようなシナリオの解決策を提供していませんが、これはデータの一貫性と正しい動作にとって非常に重要です。

これを考慮したAngular 2のカスタムバリデーターの実装を参照してください:https : //gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30

otherControl.valueChanges.subscribe()他のコントロールの変更をリッスンしthisControl.updateValueAndValidity()、他のコントロールが変更されたときに検証の別のラウンドをトリガーするために使用しています。


私は将来の参考のために以下のコードをコピーしています:

match-other-validator.ts

import {FormControl} from '@angular/forms';


export function matchOtherValidator (otherControlName: string) {

  let thisControl: FormControl;
  let otherControl: FormControl;

  return function matchOtherValidate (control: FormControl) {

    if (!control.parent) {
      return null;
    }

    // Initializing the validator.
    if (!thisControl) {
      thisControl = control;
      otherControl = control.parent.get(otherControlName) as FormControl;
      if (!otherControl) {
        throw new Error('matchOtherValidator(): other control is not found in parent group');
      }
      otherControl.valueChanges.subscribe(() => {
        thisControl.updateValueAndValidity();
      });
    }

    if (!otherControl) {
      return null;
    }

    if (otherControl.value !== thisControl.value) {
      return {
        matchOther: true
      };
    }

    return null;

  }

}

使用法

リアクティブフォームで使用する方法は次のとおりです。

private constructForm () {
  this.form = this.formBuilder.group({
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    password: ['', Validators.required],
    repeatPassword: ['', [
      Validators.required,
      matchOtherValidator('password')
    ]]
  });
}

より最新のバリデーターはここにあります:moebius-mlm / ng-validators


素敵な答え!!私は何時間もこのような解決策を探していました!少し変更を検討してください:関数を返すときに「this」参照を失う代わりに、次のような関数を返します:return(control:FormControl)=> {/ * code * /}
Vingtoft

お役に立てて嬉しいです。なぜ参照する必要thisがあるのですか?実際には、デバッグのために名前付きの関数を用意するのは良いことです。
Slava Fomin II

パフォーマンス?それは機能していますが、パフォーマンスに関しては、それは良い解決策ではないと思います。'theOtherControl'の値が変更されたときに 'thisControl'を更新するとループが発生しますね。
nightElf91

いつ退会する必要がありますか?othercontrol.valuechanges.subscribeどこでも退会しませんでした。
juana pu

@juanapuが破棄されると、AngularがvalueChangesオブザーバブルを終了すると想定しotherControlます。これにより、サブスクリプションも終了します。ただし、懸念事項は有効である可能性があります。さまざまなテストケースを使用して、このコードを最新バージョンのAngularで徹底的にデバッグすることをお勧めします。問題が見つかった場合は報告してください。
Slava Fomin II

23

Angular 2 RC.5を使用していますが、Daveからの役立つ回答に基づいて、ControlGroupが見つかりませんでした。代わりにFormGroupが機能することがわかりました。だから私はデイブのコードにいくつかのマイナーアップデートを行い、他の人と共有したいと思いました。

コンポーネントファイルで、FormGroupのインポートを追加します。

import {FormGroup} from "@angular/forms";

フォームコントロールに直接アクセスする必要がある場合に備えて、入力を定義します。

oldPassword = new FormControl("", Validators.required);
newPassword = new FormControl("", Validators.required);
newPasswordAgain = new FormControl("", Validators.required);

コンストラクターで、フォームをインスタンス化します。

this.form = fb.group({
  "oldPassword": this.oldPassword,
  "newPassword": this.newPassword,
  "newPasswordAgain": this.newPasswordAgain
}, {validator: this.matchingPasswords('newPassword', 'newPasswordAgain')});

クラスにmatchingPasswords関数を追加します。

matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: FormGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

これがRC.5を使用している人たちに役立つことを願っています。RC.6ではまだテストしていません。


@Sam最終バージョンで動作するように何かを変更しましたか?それは私のために機能していません。} 'はタイプ' ValidatorFn 'のパラメーターに割り当てることができません。
xtof 2017

いいえ、何も変更する必要はありませんでした。私にとっては、上記のサンプルコードはAngular2 finalで動作しました。上記のような正確なコードを使用していますか?
サム

良い解決策@Chang。確認パスワードを入力した後でパスワードを変更した場合。検証は機能しません。試すことができますif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika

16

角度のあるソースを掘り下げることはたくさんありますが、より良い方法を見つけました。

constructor(...) {
    this.formGroup = builder.group({
        first_name:        ['', Validators.required],
        matching_password: builder.group({
            password: ['', Validators.required],
            confirm:  ['', Validators.required]
        }, this.matchPassword)
    });

    // expose easy access to passworGroup to html
    this.passwordGroup = this.formGroup.controls.matching_password;
}

matchPassword(group): any {
    let password = group.controls.password;
    let confirm = group.controls.confirm;

    // Don't kick in until user touches both fields   
    if (password.pristine || confirm.pristine) {
      return null;
    }

    // Mark group as touched so we can add invalid class easily
    group.markAsTouched();

    if (password.value === confirm.value) {
      return null;
    }

    return {
      isValid: false
    };
}

パスワードグループのHTML部分

<div ng-control-group="matching_password" [class.invalid]="passwordGroup.touched && !passwordGroup.valid">
    <div *ng-if="passwordGroup.touched && !passwordGroup.valid">Passwords must match.</div>
    <div class="form-field">
        <label>Password</label>
        <input type="password" ng-control="password" placeholder="Your password" />
    </div>
    <div class="form-field">
        <label>Password Confirmation</label>
        <input type="password" ng-control="confirm" placeholder="Password Confirmation" />
    </div>
</div>

matching_passwordの検証が実行されると、firstNameコントロールも評価されますか?私は欲しくない!
Pascal

16

それは正確ではないので、マシューダニエルの答えを拡張する。以下は、バリデーターをに正しく割り当てる方法を示すコード例ですControlGroup

import {Component} from angular2/core
import {FormBuilder, Control, ControlGroup, Validators} from 'angular2/common'

@Component({
  selector: 'my-app',
  template: `
    <form [ngFormModel]="form">
      <label for="name">Name:</label>
      <input id="name" type="text" ngControl="name">
      <br>
      <label for="email">Email:</label>
      <input id="email" type="email" ngControl="email">
      <br>
      <div ngControlGroup="matchingPassword">
        <label for="password">Password:</label>
        <input id="password" type="password" ngControl="password">
        <br>
        <label for="confirmPassword">Confirm Password:</label>
        <input id="confirmPassword" type="password" ngControl="confirmPassword">
      </div>
    </form>
    <p>Valid?: {{form.valid}}</p>
    <pre>{{form.value | json}}</pre>
  `
})
export class App {
  form: ControlGroup
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      name: ['', Validators.required],
      email: ['', Validators.required]
      matchingPassword: fb.group({
        password: ['', Validators.required],
        confirmPassword: ['', Validators.required]
      }, {validator: this.areEqual})
    });
  }

  areEqual(group: ControlGroup) {
    let val;
    let valid = true;

    for (name in group.controls) {
      if (val === undefined) {
        val = group.controls[name].value
      } else {
        if (val !== group.controls[name].value) {
          valid = false;
          break;
        }
      }
    }

    if (valid) {
      return null;
    }

    return {
      areEqual: true
    };
  }
}

これが実際の例です:http : //plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview


ラジオボタンとチェックボックスを追加して、これら2つの値を取得する方法を教えてください。
Pardeep Jain

2
ControlGroupFormGroupこれを見ている人のために削除されます。ドキュメントAngular2の学習の例
2017

2

ここで私が思いついた別のオプションは、全体またはサブに依存せずControlGroup、それぞれに直接関連付けられていますControl

私が抱えていた問題は、互いに依存しているコントロールが階層的に一緒になっていないため、 ControlGroupです。また、私のCSSは、各コントロールが既存の角度クラスを利用してエラースタイルを表示するかどうかを決定するように設定されていました。これは、コントロール固有の検証ではなくグループ検証を処理する場合により複雑でした。検証は個々のコントロールではなくコントロールのグループに関連付けられていたため、単一のコントロールが有効であるかどうかを判断することは不可能でした。

私の場合、別のフィールドが必要かどうかを決定するために、選択ボックスの値が必要でした。

これは、コンポーネントのフォームビルダーを使用して構築されています。selectモデルの場合、リクエストオブジェクトの値に直接バインドする代わりに、コントロールの「変更時」イベントを処理できるようにするget / set関数にバインドしました。次に、選択したコントロールの新しい値に応じて、別のコントロールの検証を手動で設定できます。

関連するビュー部分は次のとおりです。

<select [ngFormControl]="form.controls.employee" [(ngModel)]="employeeModel">
  <option value="" selected></option>
  <option value="Yes">Yes</option>
  <option value="No">No</option>
</select>
...
<input [ngFormControl]="form.controls.employeeID" type="text" maxlength="255" [(ngModel)]="request.empID" />

関連するコンポーネント部分:

export class RequestComponent {
  form: ControlGroup;
  request: RequestItem;

  constructor(private fb: FormBuilder) {
      this.form = fb.group({
        employee: new Control("", Validators.required),
        empID: new Control("", Validators.compose([Validators.pattern("[0-9]{7}"]))
      });

  get employeeModel() {
    return this.request.isEmployee;
  }

  set employeeModel(value) {
    this.request.isEmployee = value;
    if (value === "Yes") {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}"), Validators.required]);
      this.form.controls["empID"].updateValueAndValidity();
    }
    else {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}")]);
      this.form.controls["empID"].updateValueAndValidity();
    }
  }
}

私の場合、常にコントロールにパターン検証を結び付けていたので、これvalidatorは常に何かに設定されていますがvalidator、コントロールに関連付けられた検証がない場合は、nullに設定できると思います。

更新:(ngModelChange)=changeFunctionName($event)を使用して値の変更を制御するなど、モデルの変更をキャプチャする他の方法があります。this.form.controls["employee"].valueChanges.subscribe(data => ...))



1

これも探していてequalTo、ng2-validationパッケージ(https://www.npmjs.com/package/ng2-validation)から使用することになりました

次に例を示します:テンプレート駆動:

<input type="password" ngModel name="password" #password="ngModel" required/>
<p *ngIf="password.errors?.required">required error</p>
<input type="password" ngModel name="certainPassword" #certainPassword="ngModel" [equalTo]="password"/>
<p *ngIf="certainPassword.errors?.equalTo">equalTo error</p>

モデル駆動:

let password = new FormControl('', Validators.required);
let certainPassword = new FormControl('', CustomValidators.equalTo(password));

this.form = new FormGroup({
  password: password,
  certainPassword: certainPassword
});

テンプレート:

<form [formGroup]="form">
  <input type="password" formControlName="password"/>
  <p *ngIf="form.controls.password.errors?.required">required error</p>
  <input type="password" formControlName="certainPassword"/>
  <p *ngIf="form.controls.certainPassword.errors?.equalTo">equalTo error</p>
</form>

1

これは、あるフィールドの年齢が別のフィールドの年齢以上であることを確認するために使用した私のバージョンです。フォームグループも使用しているので、group.get関数ではなく関数を使用していますgroup.controls[]

import { FormGroup } from '@angular/forms';

export function greaterThanOrEqualTo(sourceKey: string, targetKey: string) {
    return (group: FormGroup) => {
        let sourceInput = group.get(sourceKey);
        let targetInput = group.get(targetKey);

        console.log(sourceInput);
        console.log(targetInput);

        if (targetInput.value < sourceInput.value) {
            return targetInput.setErrors({ notGreaterThanOrEqualTo: true })
        }
    }
}

そしてコンポーネントでは:

    this.form = this._fb.group({

        clientDetails: this._fb.group({
            currentAge: ['', [Validators.required, Validators.pattern('^((1[89])|([2-9][0-9])|100)$')]],
            expectedRetirementAge: ['', [Validators.required]]
        }),

    },
    {
        validator: greaterThanOrEqualTo('clientDetails.currentAge', 'clientDetails.expectedRetirementAge')
    });

0

今のところ、あなたの最善の策は、コントロールを保持するフォームグループを作成することだと思います。関数でコントロールパスをインスタンス化して検証します。例:

    this.password = new Control('', Validators.required);
    let x = this.password;
    this.confirm = new Control('', function(c: Control){
        if(typeof c.value === 'undefined' || c.value == "") return {required: "password required"};
        if(c.value !== x.value)
            return {error: "password mismatch"};
        return null;
    });

これは、実行しているangularjs2のバージョンに大きく依存していることを知っています。これは2.0.0-alpha.46に対してテストされました

カスタムバリデーターを作成するなど、より優れた提案があれば(これが最善の方法かもしれません)、それを歓迎します。

編集

ControlGroupを使用して、そのグループ全体を検証することもできます。

this.formGroup = new ControlGroup({}, function(c: ControlGroup){
        var pass: Control = <Control>c.controls["password"];
        var conf: Control = <Control>c.controls["confirm"];
        pass.setErrors(null, true);
        if(pass.value != null && pass.value != ""){
            if(conf.value != pass.value){
                pass.setErrors({error: "invalid"}, true);
                return {error: "error"};
            }
        }
        return null;
    });

ドメインに応じてメッセージを編集するだけです。


0

ルイ・クルーズの答えは私にとって非常に役に立ちました。

完了するには、elseにsetErrors resetを追加するだけです。return passwordConfirmationInput.setErrors(null);

そして、すべてうまくいきます!

ありがとうございます、

よろしく、

TGA


0

Angular 8パスワード確認フィールドで検証する例

参考:この検証に合格した後でメインの「パスワード」フィールドが変更された場合、passwordConfirmフィールドの検証更新されません。ただし、ユーザーがパスワードフィールドに入力するときに、パスワードの確認フィールドを無効にすることができます。

<input
  type="password"
  formControlName="password"
  (input)="registerForm.get('passwordConfirm').setErrors({'passwordMatches': true})"
/>

register.component.ts

import { PasswordConfirmValidator } from './password-confirm-validator';
export class RegisterComponent implements OnInit {
  registerForm: FormGroup = this.createRegisterForm({
    username: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [
      Validators.required,
      Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$'),
      Validators.minLength(8)
    ]),
    passwordConfirm: new FormControl('', [
      Validators.required,
      PasswordConfirmValidator //custom validator
    ])
  });
}

password-confirm-validator.ts

import { AbstractControl } from '@angular/forms';

export function PasswordConfirmValidator(control: AbstractControl) {
  if(void 0 === control){ return null; }
  if(
    void 0 !== control.parent &&
    void 0 !== control.parent.controls &&
    void 0 !== control.parent.controls['password'] &&
    control.parent.controls['password'].value === control.value
  ){
    return null;
  }
  return {passwordMatches: true};
}

register.component.html

{{registerForm.get('passwordConfirm').hasError('passwordMatches')}}

-2

ライブラリの使用をお勧めしますng-form-rules。これは、検証ロジックがコンポーネントから切り離されており、フォームの他の領域の値の変更に依存する可能性がある、あらゆる種類のフォームを作成するための素晴らしいライブラリです。彼らは素晴らしいドキュメント、そしてその機能の多くを示すビデオを持っています。このような検証を行うのは簡単です。

READMEで、高レベルの情報と基本的な例を確認できます。


2
すべてにライブラリがあるという考えは好きではありません...ライブラリはこの問題の解決策ではありません。多くの場合、別のライブラリを使用するだけで新しい問題が発生します。また、Angularが更新されたときに最新の状態に保つ必要があります。フレームワークが意図するように角度のあるフォームを使用しないのはなぜですか?
ナディーン

-3

Angular 4のパスワード一致検証ルール。

エラー制御フィールドが必要な場合は、それを行うことができます。

createForm() {
    this.ngForm = this.fb.group({
       'first_name': ["", Validators.required ],
       'last_name' : ["", Validators.compose([Validators.required, Validators.minLength(3)]) ],
       'status' : ['active', Validators.compose([Validators.required])],
       'phone':[null],
       'gender':['male'],
       'address':[''],
       'email':['', Validators.compose([
          Validators.required, 
          Validators.email])],
       'password':['', Validators.compose([Validators.required])],
       'confirm_password':['', Validators.compose([Validators.required])]
    }, {validator: this.matchingPassword('password', 'confirm_password')});
  }

次に、このメソッドをconstructorメソッドLike as で宣言する必要があります。

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

ControlGroupにエラーを設定する代わりに、次のように実際のフィールドに設定します。

    matchingPassword(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirm_password = group.controls[confirmPasswordKey];

    if (password.value !== confirm_password.value) {
      return {        
        mismatchedPasswords: true
      };
    }
  }
}

パスワードグループのHTML部分

<form [formGroup]="ngForm" (ngSubmit)="ngSubmit()">
    <div class="form-group">
            <label class="control-label" for="inputBasicPassword"> Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" formControlName="password" placeholder="Password" name="password" required>
                <div class="alert text-danger" *ngIf="!ngForm.controls['password'].valid && ngForm.controls['password'].touched">This Field is Required.</div>
            </div>
            {{ngForm.value.password | json}}
            <div class="form-group">
            <label class="control-label" for="inputBasicPassword">Confirm Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" name="confirm_password" formControlName="confirm_password" placeholder="Confirm Password" match-password="password">

    <div class='alert text-danger' *ngIf="ngForm.controls.confirm_password.touched && ngForm.hasError('mismatchedPasswords')">
              Passwords doesn't match.
      </div>
    </div>
<button type="submit" [disabled]="!ngForm.valid" class="btn btn-primary ladda-button" data-plugin="ladda" data-style="expand-left" disabled="disabled"><span class="ladda-label">
            <i class="fa fa-save"></i>  Create an account
        <span class="ladda-spinner"></span><div class="ladda-progress" style="width: 0px;"></div>
        </span><span class="ladda-spinner"></span></button>
</form>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.