2017-02-10 59 views
1

我遇到了我編寫的自定義驗證程序的問題。驗證器用於驗證組件中的所有數據。Angular2 - 使用舊數據的自定義驗證程序

這裏的設置:

部件顯示與數據的X行的表。一些行是隻顯示模式,其他行將處於編輯模式(表中的某些單元格將具有輸入,選擇等)。備份表是一組數據對象(tableData)。

如果一行處於編輯模式,則每個輸入都雙向綁定到tableData數組中的相應元素。

我的自定義驗證器應用於表單標籤並將tableData作爲輸入。一切主要工作。驗證數據查看錶中的每一行,並執行我需要的所有操作。

問題是基於我的自定義驗證程序的數據是舊數據。因此,如果一行處於編輯模式,當我更改select中的值時,tableData會更新,但傳遞給驗證程序的版本會在更新之前更新。所以我總是驗證舊版本的tableData。

我不知道如何得到驗證使用最新版本的tableData。我認爲這個問題可能與選擇綁定更改tableData數組中某個對象的值的事實有關,但tableData數組本身並未實際更改。

我試着在正在編輯的行中的select上添加回調(更改)事件。使用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; 
     } 
    } 
} 

... 

這裏的驗證:

@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

反正這是錯誤的。如果你的數據不受控制,那麼你需要這樣做,而不是以另一種方式傳遞數據。 –