基于毫秒日期数组过滤带子类别的对象数组并实现日历ng-repeat
Got it, let's walk through how to solve this problem step by step—filtering the availability data to match your target dates and rendering it cleanly in an AngularJS calendar with ng-repeat.
First, we'll process your original people array to only keep availability entries that match the dates from your moment.js-generated array. We can do this right in your AngularJS controller:
// Assume your raw people data is stored in $scope.people // And your moment-generated target dates are in $scope.targetDates // Convert target dates to a Set for faster lookups (great for large datasets) const targetDateSet = new Set($scope.targetDates); // Map over each person and filter their availability $scope.filteredPeople = $scope.people.map(person => ({ ...person, availability: person.availability.filter(avail => targetDateSet.has(avail.date)) }));
This creates a new array where each person's availability only includes entries that exist in your target date list. Using a Set makes the date check O(1) instead of O(n), which is a nice performance boost if you're dealing with lots of dates or people.
Now we can build the calendar view. There are two clean ways to structure this—either group by date first, or iterate through dates and pull in matching person data. Here's the most intuitive approach for a calendar layout:
Option 1: Pre-group data by date (simpler view)
First, restructure the filtered data to be date-centric in your controller:
$scope.calendarDays = $scope.targetDates.map(date => ({ date: date, formattedDate: moment(date).format('MMMM Do, YYYY'), // Pre-format for the view people: $scope.filteredPeople .map(person => { const dayAvailability = person.availability.find(avail => avail.date === date); return { id: person.id, name: person.name, times: dayAvailability ? dayAvailability.times : [] }; }) .filter(person => person.times.length > 0) // Optional: Hide people with no slots that day }));
Then render it in your view:
<div class="calendar-container"> <!-- Repeat over each day in the calendar --> <div ng-repeat="day in calendarDays track by day.date" class="calendar-day"> <h3 class="day-header">{{ day.formattedDate }}</h3> <!-- Repeat over people with availability that day --> <div ng-repeat="person in day.people track by person.id" class="person-slot"> <h4>{{ person.name }}</h4> <!-- Repeat over available times --> <span ng-repeat="time in person.times track by time" class="time-badge"> {{ time }} </span> </div> </div> </div>
Option 2: Iterate dates and fetch person data on the fly
If you prefer not to pre-group the data, you can add a helper function to your controller to pull a person's times for a specific date:
$scope.getPersonTimesForDate = (person, targetDate) => { const matchingAvail = person.availability.find(avail => avail.date === targetDate); return matchingAvail ? matchingAvail.times : []; };
Then use it directly in your view:
<div class="calendar-container"> <div ng-repeat="date in targetDates track by date" class="calendar-day"> <h3>{{ date | moment: 'MMMM Do, YYYY' }}</h3> <!-- Use moment filter if you've imported it --> <div ng-repeat="person in filteredPeople track by person.id" class="person-slot"> <h4>{{ person.name }}</h4> <span ng-repeat="time in getPersonTimesForDate(person, date) track by time" class="time-badge"> {{ time }} </span> </div> </div> </div>
Note: To use the moment filter in the view, you'll need to include the angular-moment plugin, or just pre-format dates in the controller like we did in Option 1 to keep view logic minimal.
- Always use
track byinng-repeat(liketrack by day.dateortrack by person.id) to prevent unnecessary DOM re-renders and improve performance. - If you're working with large datasets, pre-grouping the data (Option 1) will be faster than calling a helper function in the view for every person-date pair.
- Double-check that your date timestamps are exactly matching (no off-by-one errors from time zones—moment.js should handle this if you generated the target dates consistently).
内容的提问来源于stack exchange,提问作者T. Evans

