我有一个与Typescript ViewModel结合的选择控件,Select具有默认选项("选择..."),该选项应在页面加载中显示。如果将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());
}
};
}
初始期间通过
{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"}
所以我的问题是..在一段时间内传递时,如何将其映射到上面的类型并将其分配给可观察到的"选定",我是否使控件显示正确的选择?定制版上的所有单个属性是否需要可观察到?
我从瑞安·尼梅耶(Ryan Niemeyer)操纵选项作为可观察到的选项时已经看过这一点,我是否需要用类似的构建总体数组的方式替换计算的方法?我已经尝试过,但是没有成功。
我认为您遇到的问题是您要选择的默认值不在可用选项列表中。每次调用mapcustomperiod时,都会创建一个新对象。即使该对象的内容与列表中一个对象的内容相同,对象本身是两个完全不同的对象实例,并且不是等效的。
在填充选项列表之后,请尝试设置默认值,并通过循环浏览现有选项以找到符合您要定义"等于"的任何标准的选项来设置它。
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;
}
}
}
}
处理空状态应该就像在绑定的选项上设置 optionsCaption
一样简单。
<select data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountry,
>>-------> optionsCaption: 'Choose...'"></select>
http://knockoutjs.com/documentation/options-binding.html