2017-02-10 6 views
1

私が作成したカスタムバリデータに問題があります。バリデーターは、コンポーネント内のすべてのデータを検証するために使用されます。Angular2 - 古いデータを使用するカスタムバリデータ

セットアップは次のとおりです。

コンポーネントは、X行のデータを含む表を表示します。いくつかの行は表示専用モードで、他の行は編集モードになります(テーブル内の特定のセルには入力、選択などがあります)。テーブルのバックアップは、データオブジェクト(tableData)の配列です。

行が編集モードの場合、各入力はtableData配列の適切な要素に双方向でバインドされます。

私のカスタムバリデーターはformタグに適用され、tableDataを入力として受け取ります。すべてがほとんど機能します。検証データはテーブルの各行を調べ、必要なすべてを行います。

私のカスタムバリデータに基づくデータは古いデータです。したがって、行が編集モードの場合、selectの値を変更すると、tableDataは更新されますが、バリデータに渡されるバージョンは更新前です。だから、私は常に古いバージョンのtableDataを検証しています。

最新のバージョンのtableDataを使用するように検証する方法がわかりません。私は問題は、selectバインディングがtableData配列内のオブジェクトの値を変更するが、tableData配列自体は実際には変更されないという事実に関連していると思う。

編集中の行のselectの(change)イベントにコールバックを追加しようとしました。 on(変更)メソッドは、ChangeDetectorRefを使用して手動で変更検出をトリガしますが、動作しませんでした。

私はすべてのファイルすべてをスパムしたくないので、重要なスニペットを追加しようとしました。ここで

はテンプレートです:ここでは

<form #f="ngForm" novalidate custom-validator="{{tableData | json}}"> 
    <p-dataTable [value]="tableData"> 
    ... 

     <p-column [header]="'Program Name'"> 
      <template let-row="rowData" let-idx="rowIndex" pTemplate type="body"> 
      <span *ngIf="!row['edit']"> 
       {{row['data'].programName}} 
      </span> 
       <div *ngIf="row['edit']"> 
        <select #progName="ngModel" [(ngModel)]="row['data'].programCode" 
          title="Select Program" required (change)="onProgramChange($event, idx)" 
          name="programSelect-{{idx}}"> 
         <option [value]=""></option> 
         <option *ngFor="let prog of programList" [value]="prog.code"> 
          {{prog.name}} 
         </option> 
        </select> 
       </div> 
      </template> 
     </p-column> 
    ... 

    </p-dataTable> 
</form> 

は、バッキングコンポーネントの:

//imports... 

... 

private tableData: PersonAssignmentRowData[] = []; 
private programList: Program[] = []; 

... 

onProgramChange(event: any, index: number) { 

    for(let prog of this.programList) { 
     if(prog.code == event.target.value) { 
      this.tableData[index].data.programAcronym = prog.acronym; 
      this.tableData[index].data.programLocation = prog.location; 
      this.tableData[index].data.programName = prog.name; 
      break; 
     } 
    } 
} 

... 

はここにValidatorの:

@Directive({ 
    selector: '[custom-validator]', 
    providers:[{provide: NG_VALIDATORS, useExisting: CustomValidator, multi: true}] 
}) 
export class CustomValidator implements Validator{ 

    @Input('custom-validator') tableDataString: string; 

    validate(control: AbstractControl) { 
     if(this.tableDataString == null || this.tableDataString.length == 0) { 
      return null; 
     } 

     let tableData: PersonAssignmentRowData[] = []; 
     tableData = JSON.parse(this.tableDataString); 

     let message: string = ''; 

     //logic that tests the validity of the data and sets any error messages in the message variable 

     if(message.length > 0) { 
      return {'validationMessage': message}; 
     } else { 
      return null; 
     } 
    } 
} 
+1

コードなしで何が間違っているか把握することは不可能です。 –

+0

私の質問をコードで更新しました。 –

答えて

1

は、今では明らかです。もちろん、それは動作しません。バリデータがチェックする唯一のデータソースは、validate()メソッドに渡されるコントロールです。 @Inputs()やそのようなものはありません。唯一の違いは、以下のcontrol.valueにはテーブル内だけでなく、フォーム内のすべてのコントロールのすべての値が含まれるため、テーブルが正しい入れ子になった値を選択する必要があることです。

@Directive({ 
    selector: '[custom-validator]', 
    providers:[{provide: NG_VALIDATORS, useExisting: forwardRef(() => CustomValidator), multi: true}] 
}) 
export class CustomValidator implements Validator { 

    validate(control: AbstractControl) { 
     tableData = control.table.value; // need to figure out exact path based on your form structure 

     let message: string = ''; 

     //logic that tests the validity of the data and sets any error messages in the message variable 

     if(message.length > 0) { 
      return {'validationMessage': message}; 
     } 
     return null; 
    } 

} 
+0

私は入力を取る他のバリデータを見てきました。私が持っている問題は、コントロールにないデータを検証する必要があることです。そのため、バックリングオブジェクトを入力として渡す理由は何ですか。 –

+1

とにかくそれは間違っています。データが制御できない場合は、データを別の方法で渡すのではなく、そのようにする必要があります。 –

関連する問題