我已经为一年中的每个月创建了一个嵌套循环,并将其推送到用户界面。如何使我的代码不那么冗长,并使嵌套循环更简洁?
数据来自SharePoint终结点(odata)。
逻辑是现实事件在UI中显示。它们在Observable数组中,每个都属于一年中的一个日历月以及一个日期字段。我已经尝试了下面的一月示例,但是它变得越来越冗长,并且需要在所有月份中都这样做。可以将其缩短吗?
控制器:
var months = [{name: 'January', value: '01'},{name: 'February', value: '02'}];
if (typeof filteredJan !== null && filteredJan.length > 0) {
for(var i=0;i<filteredJan.length;i++){
filteredJan[0].Month = 'JANUARY';
filteredJan[i].StartDate = this.formatDate(filteredJan[i].StartDate);
filteredJan[i].EndDate = this.formatDate(filteredJan[i].EndDate);
if(filteredJan[i].StartDate[i].substr(0,2) === months[i].value){
console.log(months[i].name);
this.filteredDates(months)
}
debugger
this.locationsFilteredJan(filteredJan);
}
}
if (typeof filteredFeb !== null && filteredFeb.length > 0) {
for(var i=0;i<filteredFeb.length;i++){
//
filteredFeb[i].StartDate = this.formatDate(filteredFeb[i].StartDate);
filteredFeb[i].EndDate = this.formatDate(filteredFeb[i].EndDate);
this.locationsFilteredFeb(filteredFeb);
}
}
客户:
<table >
<thead>
<tbody data-bind="foreach: locationsFilteredJan">
<tr>
<td data-bind="text: Month"></td>
</tr>
</tbody>
<tr>
<th>Event</th><th>Start Date</th><th>End Date</th>
<th>Location</th>
<th>Book</th>
</tr>
</thead>
<tbody data-bind="foreach: locationsFilteredJan">
<tr>
<td data-bind="text: Title"></td>
<td data-bind="text: $parent.formatDate(Start_x0020_Date)"></td>
<td data-bind="text: $parent.formatDate(End_x0020_Date)"></td>
<td data-bind="text: Location"></td>
<td><a data-bind="text: Id, attr: { href:
'https://web.powerapps.com/apps/?event_id='+ Id }">Book</a></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<td>FEBRUARY</td>
</tr>
</thead>
<tbody data-bind="foreach: locationsFilteredFeb">
<tr>
<td data-bind="text: Title"></td>
<td data-bind="text: $parent.formatDate(Start_x0020_Date)"></td>
<td data-bind="text: $parent.formatDate(End_x0020_Date)"></td>
<td data-bind="text: Location"></td>
<td><a data-bind="text: Id, attr: { href:
'https://web.powerapps.com/apps/?event_id='+ Id }">Book</a></td>
</tr>
</tbody>
</table>`
我认为最好的方法是动态处理从新的Date读取的月份循环,然后根据当前数组位置的日期(filteredJan [i] .StartDate [i])将每个月(1月,2月等)推送到UI .substr(0,2))。当前Array位置包含每个事件都有一个日期的事件,并且拔出的日历月份需要与Array中的该日期匹配,并在UI中按正确的月份对每个事件进行排序。目前,它的功能如上所述,但是太冗长,需要更简单,更快速的性能。
注意更新: 可以使它与像这样的简单对象一起工作:
var events = [
{name: 'Skiing', value: '02/01/2018'},
{name: 'Skydiving', value: '28/02/2018'},
{name: 'Sledging', value: '15/01/2018'}];
var months = [
{name: 'JANUARY', value: '09/01/2018'},
{name: 'FEBRUARY', value: '19/02/2018'}];
var companyUsers = {}// hashmap of users using companyId as keys
events.forEach(function(user){
var id= user.value.substring(3, 5);
//console.log(id);
companyUsers[id] = companyUsers[id]||[];
companyUsers[id].push(user)
});
var text = "";
// map new array based on each subscription
var res = months.map(function(sub){
sub.events = companyUsers[sub.value.substring(3, 5)] || [];
text += sub.events[sub] + "<br>";
return sub;
});
//push to view
console.log(res)
但不是这样:
<table class="table">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Start Date</th>
<th scope="col">End Date</th>
<th scope="col">Booking</th>
</tr>
</thead>
<tr><td><h4>JANUARY</h4> </td></tr>
<tbody data-bind="foreach: locationsFilteredMonths">
<tr>
<td data-bind="text: name"></td>
</tr>
</tbody>
<tbody data-bind="foreach: $parent.data[locationsFilteredMonths]">
<tr>
<td data-bind="text: Title"></td>
<td data-bind="text: $parent.formatDate(Start_x0020_Date)"></td>
<td data-bind="text: $parent.formatDate(End_x0020_Date)"></td>
<td data-bind="text: Location"></td>
<td><a data-bind="text: Id, attr: { href: 'https://web.powerapps.com/apps/?event_id='+ Id }">Book</a></td>
</tr>
</tbody>
</table>
控制器:
var months = [
{name: 'JANUARY', value: '01'},
{name: 'FEBRUARY', value: '02'},
{name: 'MARCH', value: '03'},
{name: 'APRIL', value: '04'},
{name: 'MAY', value: '05'},
{name: 'JUNE', value: '06'},
{name: 'JULYS', value: '07'},
{name: 'AUGUST', value: '08'},
{name: 'SEPTEMBER', value: '09'},
{name: 'OCTOBER', value: '10'},
{name: 'NOVEMBER', value: '11'},
{name: 'DECEMBER', value: '12'}];
var eventsHash = {};
//format API dates
if (typeof filteredEvents !== null && filteredEvents.length > 0) {
var i:any;
for(i=0;i<filteredEvents.length;i++){
filteredEvents[i].StartDate = this.formatDate(filteredEvents[i].StartDate);
filteredEvents[i].EndDate = this.formatDate(filteredEvents[i].EndDate);
}
}
filteredEvents.forEach(function(event){
//get position of month and use as id
var monthStr = event.StartDate.substring(3, 5);
console.log(monthStr);
eventsHash[monthStr] = eventsHash[monthStr]||[];
eventsHash[monthStr].push(event);
});
var filteredMonths = months.map(function(sub){
sub.value = eventsHash[sub.name];
//text += sub.events[sub] + "<br>";
return sub;
});
//for each month show events
this.locationsFilteredMonths(filteredMonths);
this.locationsFilteredYears(filteredEvents);
答案 0 :(得分:0)
一种方法是将数据转换为以月份名称作为键的对象,如下所示:
{
'January': [
{
Id: '',
Title: 'Foo',
Start_x0020_Date: '',
End_x0020_Date: '',
Location: ''
},
{
Id: '',
Title: 'Foo',
Start_x0020_Date: '',
End_x0020_Date: '',
Location: ''
}
],
'February': [
{
Id: '',
Title: 'Foo',
Start_x0020_Date: '',
End_x0020_Date: '',
Location: ''
},
{
Id: '',
Title: 'Foo',
Start_x0020_Date: '',
End_x0020_Date: '',
Location: ''
}
]
}
如何执行此操作完全取决于您的源数据,但是我假设您是从某个API获取的,这只是事件的一大集合。只需一个循环。
然后您的模板将如下所示:
<!-- ko foreach: { data: Object.keys(data), as: 'month' } -->
<table>
<thead>
<tr>
<td data-bind="text: month"></td>
</tr>
</thead>
<tbody data-bind="foreach: $parent.data[month]">
<tr>
<td data-bind="text: Title"></td>
<td data-bind="text: $parents[1].formatDate(Start_x0020_Date)"></td>
<td data-bind="text: $parents[1].formatDate(End_x0020_Date)"></td>
<td data-bind="text: Location"></td>
<td><a data-bind="text: Id, attr: { href: 'https://web.powerapps.com/apps/?event_id='+ Id }">Book</a></td>
</tr>
</tbody>
</table>
<!-- /ko -->
编辑:
这是一个工作的小提琴:https://jsfiddle.net/thebluenile/5yL0knm9/