2017-02-23 12 views
0

私はTypescriptのビューモデルにバインドされた選択コントロールを持っています。選択にはページロード時に表示されるデフォルトオプション( "選択...")があります。 viewmodelに初期期間が渡された場合は、デフォルトの設定が選択されたオプションより優先されます。デフォルトのテキストと双方向の値のバインディングを持つノックアウトバウンドの選択ドロップダウン

私は初期期間をモデルに渡すことができ、コールバックを使用して親モデルのフォームを使用してフォームにエントリを保存できます。ただし、値のバインディングコントロールで動作し、 "選択..."テキストは、初期期間ラベルが選択されたオプションではなく、コントロールに表示されたままになります。

ビュー

<div id="customPeriodSelection" data-bind="with: customPeriodSelection"> 
<select id="periodSelect" class="form-control" data-bind="value: selectedOption, event: { change: onChange }"> 
    <option>@Labels.SelectDD</option> 
    <!--ko foreach: {data: customGroups}--> 
    <optgroup data-bind="attr: { label: label}"> 
     <!--ko foreach: {data: customPeriods}--> 
     <option data-bind="text: $data.label, value: $data"></option> 
     <!-- /ko --> 
    </optgroup> 
    <!-- /ko --> 
</select> 

export class CustomPeriod { 
    constructor(
     public start: Iso8601DateString, 
     public end: Iso8601DateString, 
     public label: string) { } 

    identifier =() => { 
     return this.start + "-" + this.end; 
    } 

    static mapCustomPeriod = (period: any) => { 
     return new CustomPeriod(
      period.startDate, 
      period.endDate, 
      period.label 
     ) 
    } 
} 

export class CustomPeriodSelection { 
    customFrequencyId: number; 
    customPeriods: KnockoutObservableArray<CustomPeriod> = ko.observableArray([]); 
    selectedOption: KnockoutObservable<any> = ko.observable(); 

    constructor(
     customFrequencyId: number, 
     initialPeriod: any, 
     public callback: (customPeriod: CustomPeriod) => void 
    ) { 
     var base = this; 
     this.customFrequencyId = customFrequencyId; 

     Verco.Services.GetData("GetPeriods", { 
      frequency: customFrequencyId 
     }, 
      function (result: any[]) { 
       if (result.length > 0) { 
        _.each(result, function (customPeriod: any) { 
         base.customPeriods.push(CustomPeriod.mapCustomPeriod(customPeriod)); 
        }) 
       } 
      }); 

     if (initialPeriod !== null) { 
      var mappedPeriod = CustomPeriod.mapCustomPeriod(initialPeriod); 
      this.selectedOption(mappedPeriod); 
      this.callback(this.selectedOption()); 
     } 
    } 

    customGroups: KnockoutComputed<any[]> = ko.computed(() => { 

     var groupedList = _.groupBy(this.customPeriods(), function (customPeriod: CustomPeriod) { 
      return Verco.Format.FormatDate(customPeriod.end, DateFormats.Year); 
     }); 

     return _.map(groupedList, function (customPeriod: any) { 
      return { 
       label: Verco.Format.FormatDate(customPeriod[0].end, DateFormats.Year), 
       customPeriods: customPeriod 
      } 
     }); 
    }); 

    onChange =() => { 
     if (this.callback !== null) { 
      this.callback(this.selectedOption()); 
     } 
    }; 
} 

initialPeriodがマップ

{customFrequencyId: 1008, startDate: "2017-01-01T00:00:00Z", endDate: "2017-01-28T00:00:00Z", label: "P1 2017"} 

に渡された活字体...

CustomPeriod {start: "2017-01-01T00:00:00Z", end: "2017-01-28T00:00:00Z", label: "P1 2017"} 

私の質問は..上記の型にマッピングし、それを "selectedOption" observableに割り当てると、どのようにしてコントロールが正しい選択を表示するのですか? CustomPeriodの個々のプロパティのすべてを監視する必要がありますか?

私はRyan NiemeyerがObservableとしてOptionsを操作するため、THISを見てきましたが、Computedを置き換える必要がありますか?私は試しましたが、成功しません。

+0

あなたのコードをあまりにも掘り下げることなく、なぜあなたは 'change'イベントハンドラを使用していますか? 'value'バインディングはこれをすでに処理しています... – user3297291

+0

changeイベントはコールバック関数で使用されます。 – Hicki

答えて

0

私はあなたが抱えている問題は、あなたが選択しようとしているデフォルト値が使用可能なオプションのリストに含まれていないということだと思います。 mapCustomPeriodを呼び出すたびに、新しいオブジェクトが作成されます。そのオブジェクトの内容がリスト内の内容と同じであっても、オブジェクト自体は2つの全く異なるオブジェクトインスタンスであり、同等ではありません。

オプションリストが入力された後にデフォルトを設定し、既存のオプションをループして設定して、「等価」の定義に使用する条件に一致するものを探してみてください。

Verco.Services.GetData("GetPeriods", { 
     frequency: customFrequencyId 
    }, 
     function (result: any[]) { 
      if (result.length > 0) { 
       _.each(result, function (customPeriod: any) { 
        base.customPeriods.push(CustomPeriod.mapCustomPeriod(customPeriod)); 
       }); 
       base.setValueByLabel(initialPeriod.label); //set default via label 
      } 
     }); 
... 

this.setValueByLabel = function(label){ 
    for(var i=0; i<base.customGroups().length; i++){ 
     var group = base.customGroups()[i]; 
     for(var j=0; j<group.customPeriods.length; j++){ 
      var item = group.customPeriods[j]; 
      if(item.label === label){ 
       base.selectedOption(item); 
       return; 
      } 
     } 
    } 
} 
0

空の状態の処理は、オプションバインドでoptionsCaptionを設定するだけで簡単です。

<select data-bind="options: availableCountries, 
        optionsText: 'countryName', 
        value: selectedCountry, 
     >>-------> optionsCaption: 'Choose...'"></select> 

http://knockoutjs.com/documentation/options-binding.html

+0

選択コントロールのforeachループと一緒にOptionsCaptionを使用することができません。問題は、空の状態を表示するのではなく、選択された項目が初期値として表示されるように選択リストを更新することです。設定されていない場合、空の値が表示されます。 – Hicki

関連する問題