I am trying to create a partial view that will display a select control with grouped options.
I have an initial bit of JSON:
[{
"customFrequencyId": 1008,
"startDate": "2016-10-29T00:00:00Z",
"endDate": "2016-11-25T00:00:00Z",
"label": "P11 2016"
}, {
"customFrequencyId": 1008,
"startDate": "2016-11-26T00:00:00Z",
"endDate": "2016-12-31T00:00:00Z",
"label": "P12 2016"
}, {
"customFrequencyId": 1008,
"startDate": "2017-01-01T00:00:00Z",
"endDate": "2017-01-28T00:00:00Z",
"label": "P1 2017"
}, {
"customFrequencyId": 1008,
"startDate": "2017-01-29T00:00:00Z",
"endDate": "2017-02-25T00:00:00Z",
"label": "P2 2017"
}, {
"customFrequencyId": 1008,
"startDate": "2017-02-26T00:00:00Z",
"endDate": "2017-03-23T00:00:00Z",
"label": "P3 2017"
}]
My current TypeScript:
export class CustomPeriodSelection {
customPeriods: KnockoutObservable<any[]> = ko.observable([]);
selectedOption: KnockoutObservable<any> = ko.observable();
customGroups: KnockoutComputed<any[]> = ko.computed(() => {
var groupedList = _.groupBy(this.customPeriods(), function (item: any) {
return item.endDate.substring(0, 4);
});
return _.map(groupedList, function (item: any) {
return item;
});
});
constructor(
customPeriods: any[]
) {
this.customPeriods(customPeriods);
}
}
My intention is to end up with the following JSON from the Knockout computed...
[{
"label": 2016,
"customPeriods": [{
"customFrequencyId": 1008,
"startDate": "2016-10-29T00:00:00Z",
"endDate": "2016-11-25T00:00:00Z",
"label": "P11 2016"
}, {
"customFrequencyId": 1008,
"startDate": "2016-11-26T00:00:00Z",
"endDate": "2016-12-31T00:00:00Z",
"label": "P12 2016"
}]
}, {
"label": 2017,
"customPeriods": [{
"customFrequencyId": 1008,
"startDate": "2017-01-01T00:00:00Z",
"endDate": "2017-01-28T00:00:00Z",
"label": "P1 2017"
}, {
"customFrequencyId": 1008,
"startDate": "2017-01-29T00:00:00Z",
"endDate": "2017-02-25T00:00:00Z",
"label": "P2 2017"
}, {
"customFrequencyId": 1008,
"startDate": "2017-02-26T00:00:00Z",
"endDate": "2017-03-23T00:00:00Z",
"label": "P3 2017"
}]
}]
Which will then be put to the select control like this..
<select class="form-control" data-bind="foreach: customGroups, event: { change: periodChanged }">
<optgroup data-bind="attr: { label: $data.label}, foreach: customPeriods">
<option data-bind="text: $data.label, value: $data"></option>
</optgroup>
</select>
I'm assuming it is the implementation of groupBy & map that are incorrect. How do I group the customPeriods array by year, and then map the result to a new array with the required structure above?
I currently get the following from the code I have written.
[
[
{
"customFrequencyId": 1008,
"startDate": "2016-10-29T00:00:00Z",
"endDate": "2016-11-25T00:00:00Z",
"label": "P11 2016"
},
{
"customFrequencyId": 1008,
"startDate": "2016-11-26T00:00:00Z",
"endDate": "2016-12-31T00:00:00Z",
"label": "P12 2016"
}
],
[
{
"customFrequencyId": 1008,
"startDate": "2017-01-01T00:00:00Z",
"endDate": "2017-01-28T00:00:00Z",
"label": "P1 2017"
},
{
"customFrequencyId": 1008,
"startDate": "2017-01-29T00:00:00Z",
"endDate": "2017-02-25T00:00:00Z",
"label": "P2 2017"
},
{
"customFrequencyId": 1008,
"startDate": "2017-02-26T00:00:00Z",
"endDate": "2017-03-23T00:00:00Z",
"label": "P3 2017"
}
]
]
I have read other questions but I'm struggling. Any help would be greatly appreciated (with an explanation if possible as opposed to just doing it for me). Thanks!
You're close.
Change:
return _.map(groupedList, function (item: any) {
return item;
});
to
return _.map(groupedList, function (item: any) {
return { label: item[0].endDate.substring(0, 4), customPeriods: item };
});
Though I'd like to verify this in a plunker first.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.