Javascript 角度1.x过滤器-修改过滤元素会影响原始阵列

Javascript 角度1.x过滤器-修改过滤元素会影响原始阵列,javascript,angularjs,filter,Javascript,Angularjs,Filter,背景信息 旅行社每天都有旅行团出发。在每一个旅行团中,都有不同数量的旅行团——同一旅行团出发的不同车辆在同一天同一时间运行 对于列出所有预定旅行的管理系统,我正在构建一个过滤器,它可以做两件事: 1) 如果选中筛选日的任何复选框(周一、周二、周三等),则仅显示在这些选定日运行的巡演 2) 如果选中筛选组(第一组、第二组、第三组等)的任何复选框,则仅显示这些组。例如:如果一个巡演只有一个组,并且选中了第二个组的复选框,则该组将不显示。如果一个巡演有三个组,并且选中了第二个组的相同复选框,则只显示第

背景信息

旅行社每天都有旅行团出发。在每一个旅行团中,都有不同数量的旅行团——同一旅行团出发的不同车辆在同一天同一时间运行

对于列出所有预定旅行的管理系统,我正在构建一个过滤器,它可以做两件事:

1) 如果选中筛选日的任何复选框(周一、周二、周三等),则仅显示在这些选定日运行的巡演

2) 如果选中筛选组(第一组、第二组、第三组等)的任何复选框,则仅显示这些组。例如:如果一个巡演只有一个组,并且选中了第二个组的复选框,则该组将不显示。如果一个巡演有三个组,并且选中了第二个组的相同复选框,则只显示第二个组

问题

日间过滤部分工作得非常好。筛选器的组顺序部分没有。在过滤器中,每当我从
filteredparties
数组中的
groups
对象中删除组时,它都会影响原始
departies
数组。每当我选中第一个组顺序过滤器复选框时,除第一个组外的所有组都会消失,但当我取消选中同一复选框时,这些组不会重新出现,因为它们实际上已从原始
偏差
数组中删除

这是我的过滤代码:

app.filter('departuresFilter', function() { //Filter departures
    return function(departures, filterOptions) {

        if (typeof departures !== 'undefined') //If there are departures
        {
            var filteredDepartures = []; //Create new array

            //See if days should be filtered
            filterOptions.daysFiltered = false; //Assuming days won't be filtered
            filterOptions.days.forEach(function(day) {
                if (day.selected) //Day is selected
                    filterOptions.daysFiltered = true;
            });

            //See if group orders should be filtered
            //The array groupsInDepartures is an array that has as many elements as the highest amount of groups on any day within selected date range (typically 1-3 elements)
            filterOptions.groupOrdersFiltered = false; //Assuming group orders won't be filtered
            filterOptions.groupsInDepartures.groups.forEach(function (group) { //For every group order.
                if (group.selected) //A checkbox has been selected
                    filterOptions.groupOrdersFiltered = true;
            }); 

            for (i = 0; i < departures.length; i++) //For every tour departure
            {
                var removeDeparture = false; //Assuming departure will not be removed

                if (filterOptions.daysFiltered) //Days are filtered
                {
                    filterOptions.days.forEach(function(day) { //For every day in filter array
                        if (day.title == departures[i].date.D) //Found this group's day in day filter array
                        {
                            if (day.selected == false) //This day is not selected (should not show)
                                removeDeparture = true; //Remove day
                        }
                    });
                }

                //Departure is not to be removed - check if any groups should be removed
                if (removeDeparture == false)
                {
                    filteredDepartures.push(departures[i]); //Add departure to filtered departures array

                    if (filterOptions.groupOrdersFiltered) //Group orders should be filtered. Only show groups of which their corresponding checkbox has been selected.
                    {
                        var departureIndex = filteredDepartures.length - 1; //Get index for last departure

                        for (j = filteredDepartures[departureIndex].groups.length; j > 0; j--) //For every group in departure. Start from above, to not mess up indexes.
                        {
                            if (!filterOptions.groupsInDepartures.groups[j - 1].selected) //This group should be removed
                                filteredDepartures[departureIndex].groups.splice((j - 1), 1); //Remove group
                        }
                    }
                }
            }

            return filteredDepartures;
        }
    };
});
我也尝试过用JSON刺痛
偏离
数组,然后在过滤器中创建一个全新的对象,以删除对原始数组的任何引用,但是Angular给了我一个关于周期太多的错误消息

编辑

张贴HTML以及。第一个表用于选择日期、筛选日期和组(大小类型筛选尚未激活)。第二个表用于生成旅游出发列表

<table style="margin: 40px 0;">
    <tr>
        <td>
            <h2>Dates</h2>
        </td>
        <td style="padding-left: 40px;">
            <h2>Filter groups</h2>
        </td>
        <td style="padding-left: 40px;">
            <h2>Filters applied</h2>
        </td>
    </tr>
    <tr>
        <td style="vertical-align: top;">
            <ul class="cleanList">
                <li>From <input type="text" class="form-control" ng-model="dateStart" style="width: 120px; text-align: center;" ng-change="loadGroups()" jqdatepicker></li>
                <li>To<input type="text" class="form-control" ng-model="dateEnd" style="width: 120px; text-align: center;" ng-change="loadGroups()" jqdatepicker></li>
            </ul>
        </td>
        <td style="padding-left: 40px; vertical-align: top;">
            Size Type
            <select class="form-control" ng-model="filterOptions.sizeType">
                <option></option>
                <option ng-repeat="sizeType in groupSizeTypes" value="{{ sizeType.id }}">{{ sizeType.title }}</option>
            </select>

            <ul class="horList">
                <li ng-repeat="day in filterOptions.days">
                    <div><label for="{{ day.title }}">{{ day.title }}</label></div>
                    <div style="text-align: center;"><input type="checkbox" id="{{ day.title }}" ng-model="day.selected"></div>
                </li>
            </ul>

            <div ng-show="filterOptions.groupsInDepartures.groups.length > 0">
                Groups
                <ul class="horList">
                    <li ng-repeat="group in filterOptions.groupsInDepartures.groups">
                        <div><label for="nth_group_{{ group.order }}">{{ group.order }}</label></div>
                        <div style="text-align: center;"><input type="checkbox" id="nth_group_{{ group.order }}" ng-model="group.selected"></div>
                    </li>
                </ul>
            </div>
        </td>
        <td style="padding-left: 40px; vertical-align: top;" ng-show="filterOptions.tag != '' || filterOptions.daysFiltered || filterOptions.groupOrdersFiltered">
            <ul>
                <li ng-show="filterOptions.tag != ''">Tag</li>
                <li ng-show="filterOptions.daysFiltered">Days</li>
                <li ng-show="filterOptions.groupOrdersFiltered">Groups</li>
            </ul>
        </td>
    </tr>
</table>

{{ departures }} <!-- for debugging (filtering groups from filteredDepartures removes them from this array as well) -->

<p id="loadWrap" style="display: none;"><span class="loadBox"><img src="/images/misc/ajax-loader.gif">Loading</span></p>
<p ng-show="filteredDepartures.length" class="small"><i>Showing {{ filteredDepartures.length }} departures.</i></p>

<table class="table">
    <tr>
        <th>Date</th>
        <th>Tour</th>
        <th>Size type</th>
        <th>Pax</th>
        <th>Guide</th>
        <th>Salary K CLP</th>
        <th>Vehicle</th>
        <th>Rental K CLP</th>
    </tr>
    <tbody ng-repeat="departure in filteredDepartures = (departures | departuresFilter:filterOptions)">
        <tr class="danger">
            <td><a style="cursor: pointer;" ng-click="loadThisDate(departure.date.Ymd)">{{ departure.date.Mj }}</a><div class="small" style="color: gray;">{{ departure.date.D }}</div></td>
            <td>{{ departure.tour.title }}</td>
            <td>{{ departure.tour.sizeType.title }}</td>
            <td colspan="5"></td>
        </tr>
        <tr ng-repeat="group in departure.groups" class="trNoTopBorder danger">
            <td colspan="3"></td>
            <td>{{ group.pax }} / {{ group.capacity }}</td>
            <td>{{ group.guide.name }}</td>
            <td>{{ group.salaryKCLP }}</td>
            <td>{{ group.vehicle.name }}</td>
            <td>{{ group.vehicleRentalKCLP }}</td>
        </tr>
    </tbody>
</table>

日期
过滤组
应用的过滤器
尺寸类型 {{sizeType.title}
  • {{day.title}}
  • {{group.order}
    标签 过滤的天数
{{出发}} 加载

显示{{{filteredparties.length}}偏差

日期 游览 尺寸类型 圣像牌 指导 中电薪酬 车辆 中电租赁 {{出发日期.Mj}{{出发日期.D} {{出发.tour.title} {{execution.tour.sizeType.title} {{group.pax}/{{group.capacity} {{group.guide.name} {{group.salaryKCLP}} {{group.vehicle.name} {{group.vehicleRentalKCLP}}
首先,避免在angularjs上使用过滤器,因为它会反复调用。尽量使用指令,因为指令是最便宜的

其次,如果你想克隆一个javascript对象,你应该在FilteredParties.push上使用angular.copy,
FilteredParties.push(离开[i])
你是push原始项,它不会被克隆。使用
filteredparties.push(角度复制(偏离[i])

此外,如果过滤器选项是静态的,即不可更改,则您只能$watch离开

app.directive('departuresDirective', function () { 
    return {
        restrict: 'AC',
        link: function (scope, element, attr, ngModel) {
            var filterOptions, departures;
            scope.filteredDepartures = [];
            scope.$watchGroup([attr.filterOptions, attr.departures], function (newValues, oldValues, scope) {
                filterOptions = newValues[0];
                departures = newValues[1];
                scope.filteredDepartures =  filterDepartures(departures, filterOptions);
            }, true);

            function filterDepartures(departures, filterOptions) {
                if (typeof departures !== 'undefined') //If there are departures
                {
                    var filteredDepartures = []; //Create new array

                    //See if days should be filtered
                    filterOptions.daysFiltered = false; //Assuming days won't be filtered
                    filterOptions.days.forEach(function (day) {
                        if (day.selected) //Day is selected
                            filterOptions.daysFiltered = true;
                    });

                    //See if group orders should be filtered
                    //The array groupsInDepartures is an array that has as many elements as the highest amount of groups on any day within selected date range (typically 1-3 elements)
                    filterOptions.groupOrdersFiltered = false; //Assuming group orders won't be filtered
                    filterOptions.groupsInDepartures.groups.forEach(function (group) { //For every group order.
                        if (group.selected) //A checkbox has been selected
                            filterOptions.groupOrdersFiltered = true;
                    });

                    for (i = 0; i < departures.length; i++) //For every tour departure
                    {
                        var removeDeparture = false; //Assuming departure will not be removed

                        if (filterOptions.daysFiltered) //Days are filtered
                        {
                            filterOptions.days.forEach(function (day) { //For every day in filter array
                                if (day.title == departures[i].date.D) //Found this group's day in day filter array
                                {
                                    if (day.selected == false) //This day is not selected (should not show)
                                        removeDeparture = true; //Remove day
                                }
                            });
                        }

                        //Departure is not to be removed - check if any groups should be removed
                        if (removeDeparture == false) {
                            filteredDepartures.push(angular.copy(departures[i])); //Add departure to filtered departures array

                            if (filterOptions.groupOrdersFiltered) //Group orders should be filtered. Only show groups of which their corresponding checkbox has been selected.
                            {
                                var departureIndex = filteredDepartures.length - 1; //Get index for last departure

                                for (j = filteredDepartures[departureIndex].groups.length; j >= 0; j--) //For every group in departure. Start from above, to not mess up indexes.
                                {
                                    if (!filterOptions.groupsInDepartures.groups[j - 1].selected) //This group should be removed
                                        filteredDepartures[departureIndex].groups.splice((j - 1), 1); //Remove group
                                }
                            }
                        }
                    }

                    return filteredDepartures;
                }
            }

        }
    };
});
app.directive('departuresDirective',function(){
返回{
限制:“AC”,
链接:功能(范围、元素、属性、模型){
var滤波器选项、偏差;
scope.filteredparties=[];
作用域.$watchGroup([attr.filterOptions,attr.deferences],函数(newValues,oldValues,scope){
filterOptions=新值[0];
偏差=新值[1];
scope.FilteredParties=过滤器配件(偏差、过滤器选项);
},对);
功能过滤器部件(偏差、过滤器选项){
if(偏离类型!==“未定义”)//如果存在偏离
{
var filteredepartures=[];//创建新数组
//查看是否应过滤天数
filterOptions.daysFiltered=false;//假设不过滤天数
filterOptions.days.forEach(函数(天){
如果(day.selected)//选择了day
filterOptions.daysFiltered=true;
});
//查看是否应筛选组订单
//数组groupsindeferences是一个数组,它的元素数与所选日期范围内任何一天的最大组数相同(通常为1-3个元素)
filterOptions.groupOrdersFiltered=false;//假设不过滤组订单
filterOptions.groupsindepartitions.groups.forEach(函数(组){//对于每个gr
app.directive('departuresDirective', function () { 
    return {
        restrict: 'AC',
        link: function (scope, element, attr, ngModel) {
            var filterOptions, departures;
            scope.filteredDepartures = [];
            scope.$watchGroup([attr.filterOptions, attr.departures], function (newValues, oldValues, scope) {
                filterOptions = newValues[0];
                departures = newValues[1];
                scope.filteredDepartures =  filterDepartures(departures, filterOptions);
            }, true);

            function filterDepartures(departures, filterOptions) {
                if (typeof departures !== 'undefined') //If there are departures
                {
                    var filteredDepartures = []; //Create new array

                    //See if days should be filtered
                    filterOptions.daysFiltered = false; //Assuming days won't be filtered
                    filterOptions.days.forEach(function (day) {
                        if (day.selected) //Day is selected
                            filterOptions.daysFiltered = true;
                    });

                    //See if group orders should be filtered
                    //The array groupsInDepartures is an array that has as many elements as the highest amount of groups on any day within selected date range (typically 1-3 elements)
                    filterOptions.groupOrdersFiltered = false; //Assuming group orders won't be filtered
                    filterOptions.groupsInDepartures.groups.forEach(function (group) { //For every group order.
                        if (group.selected) //A checkbox has been selected
                            filterOptions.groupOrdersFiltered = true;
                    });

                    for (i = 0; i < departures.length; i++) //For every tour departure
                    {
                        var removeDeparture = false; //Assuming departure will not be removed

                        if (filterOptions.daysFiltered) //Days are filtered
                        {
                            filterOptions.days.forEach(function (day) { //For every day in filter array
                                if (day.title == departures[i].date.D) //Found this group's day in day filter array
                                {
                                    if (day.selected == false) //This day is not selected (should not show)
                                        removeDeparture = true; //Remove day
                                }
                            });
                        }

                        //Departure is not to be removed - check if any groups should be removed
                        if (removeDeparture == false) {
                            filteredDepartures.push(angular.copy(departures[i])); //Add departure to filtered departures array

                            if (filterOptions.groupOrdersFiltered) //Group orders should be filtered. Only show groups of which their corresponding checkbox has been selected.
                            {
                                var departureIndex = filteredDepartures.length - 1; //Get index for last departure

                                for (j = filteredDepartures[departureIndex].groups.length; j >= 0; j--) //For every group in departure. Start from above, to not mess up indexes.
                                {
                                    if (!filterOptions.groupsInDepartures.groups[j - 1].selected) //This group should be removed
                                        filteredDepartures[departureIndex].groups.splice((j - 1), 1); //Remove group
                                }
                            }
                        }
                    }

                    return filteredDepartures;
                }
            }

        }
    };
});
    <table class="table" departures-directive="" departures="departures"  filter-options="filterOptions">
    <tr>
        <th>Date</th>
        <th>Tour</th>
        <th>Size type</th>
        <th>Pax</th>
        <th>Guide</th>
        <th>Salary K CLP</th>
        <th>Vehicle</th>
        <th>Rental K CLP</th>
    </tr>
    <tbody ng-repeat="departure in filteredDepartures track by $index">
        <tr class="danger">
            <td><a style="cursor: pointer;" ng-click="loadThisDate(departure.date.Ymd)">{{ departure.date.Mj }}</a><div class="small" style="color: gray;">{{ departure.date.D }}</div></td>
            <td>{{ departure.tour.title }}</td>
            <td>{{ departure.tour.sizeType.title }}</td>
            <td colspan="5"></td>
        </tr>
        <tr ng-repeat="group in departure.groups track by $index" class="trNoTopBorder danger">
            <td colspan="3"></td>
            <td>{{ group.pax }} / {{ group.capacity }}</td>
            <td>{{ group.guide.name }}</td>
            <td>{{ group.salaryKCLP }}</td>
            <td>{{ group.vehicle.name }}</td>
            <td>{{ group.vehicleRentalKCLP }}</td>
        </tr>
    </tbody>
</table>
app.filter('departuresFilter', function() { //Filter departures
    return function(_departures, _filterOptions) {
         var departures = angular.copy(_departures);
         var filterOptions = angular.copy(_filterOptions);
        if (typeof departures !== 'undefined') //If there are departures
        {
            var filteredDepartures = []; //Create new array

            //See if days should be filtered
            filterOptions.daysFiltered = false; //Assuming days won't be filtered
            filterOptions.days.forEach(function(day) {
                if (day.selected) //Day is selected
                    filterOptions.daysFiltered = true;
            });

            //See if group orders should be filtered
            //The array groupsInDepartures is an array that has as many elements as the highest amount of groups on any day within selected date range (typically 1-3 elements)
            filterOptions.groupOrdersFiltered = false; //Assuming group orders won't be filtered
            filterOptions.groupsInDepartures.groups.forEach(function (group) { //For every group order.
                if (group.selected) //A checkbox has been selected
                    filterOptions.groupOrdersFiltered = true;
            }); 

            for (i = 0; i < departures.length; i++) //For every tour departure
            {
                var removeDeparture = false; //Assuming departure will not be removed

                if (filterOptions.daysFiltered) //Days are filtered
                {
                    filterOptions.days.forEach(function(day) { //For every day in filter array
                        if (day.title == departures[i].date.D) //Found this group's day in day filter array
                        {
                            if (day.selected == false) //This day is not selected (should not show)
                                removeDeparture = true; //Remove day
                        }
                    });
                }

                //Departure is not to be removed - check if any groups should be removed
                if (removeDeparture == false)
                {
                    filteredDepartures.push(departures[i]); //Add departure to filtered departures array

                    if (filterOptions.groupOrdersFiltered) //Group orders should be filtered. Only show groups of which their corresponding checkbox has been selected.
                    {
                        var departureIndex = filteredDepartures.length - 1; //Get index for last departure

                        for (j = filteredDepartures[departureIndex].groups.length; j >= 0; j--) //For every group in departure. Start from above, to not mess up indexes.
                        {
                            if (!filterOptions.groupsInDepartures.groups[j - 1].selected) //This group should be removed
                                filteredDepartures[departureIndex].groups.splice((j - 1), 1); //Remove group
                        }
                    }
                }
            }

            return filteredDepartures;
        }
    };
});
$scope.filterDepartures = function() { //Filter departures
    $scope.filteredDepartures = []; //Create new array
    $scope.groupCount = 0; //Reset group count var
    $scope.filterOptions.largestGroup = 0; //Var for remembering biggest group. This is for creating capacity array for editing groups.

    //See if days should be filtered
    $scope.filterOptions.daysFiltered = false; //Assuming days won't be filtered
    $scope.filterOptions.days.forEach(function(day) {
        if (day.selected) //Day is selected
            $scope.filterOptions.daysFiltered = true;
    });

    //See if group orders should be filtered
    //The array groupsInDepartures is an array that has as many elements as the highest amount of groups on any day within selected date range (typically 1-3 elements)
    $scope.filterOptions.groupOrdersFiltered = false; //Assuming group orders won't be filtered
    $scope.filterOptions.groupsInDepartures.groups.forEach(function (group) { //For every group order.
        if (group.selected) //A checkbox has been selected
            $scope.filterOptions.groupOrdersFiltered = true;
    }); 

    for (i = 0; i < $scope.departures.length; i++) //For every tour departure
    {
        var removeDeparture = false; //Assuming departure will not be removed

        if ($scope.filterOptions.daysFiltered) //Days are filtered
        {
            $scope.filterOptions.days.forEach(function(day) { //For every day in filter array
                if (day.title == $scope.departures[i].date.D) //Found this group's day in day filter array
                {
                    if (day.selected == false) //This day is not selected (should not show)
                        removeDeparture = true; //Remove day
                }
            });
        }

        //Departure is not to be removed - check if any groups should be removed
        if (removeDeparture == false)
        {
            var tempDeparture = angular.copy($scope.departures[i]); //Create temporary departure object

            for (j = (tempDeparture.groups.length - 1); j >= 0; j--) //For every group in departure. Start from above, to not mess up indexes.
            {
                var removeGroup = false; //Assuming group shouldn't be removed

                if ($scope.filterOptions.groupOrdersFiltered && !$scope.filterOptions.groupsInDepartures.groups[j].selected) //Group orders should be filtered. Only show groups of which their corresponding checkbox has been selected.
                    removeGroup = true; //Remove group later
                else //Continue checking
                {
                    //Check if guide is filtered, and if this group has the correct guide
                    if ($scope.filterOptions.guide.exists && $scope.filterOptions.guide.id != tempDeparture.groups[j].guide.id)
                        removeGroup = true;
                    else //Guide was not filtered. Continue checking
                    {
                        //Check if vehicle is filtered, and if this group has the correct vehicle
                        if ($scope.filterOptions.vehicle.exists && $scope.filterOptions.vehicle.id != tempDeparture.groups[j].vehicle.id)
                            removeGroup = true;
                    }
                }


                if (removeGroup) //Group should be removed
                    tempDeparture.groups.splice((j), 1); //Remove group
            }

            //Loop through all groups that are left, looking for largest group
            tempDeparture.groups.forEach(function (group) {
                if (group.pax > $scope.filterOptions.largestGroup) //Found bigger group
                    $scope.filterOptions.largestGroup = group.pax; //Save to var
            });

            $scope.groupCount += tempDeparture.groups.length;

            if (!$scope.filterOptions.hideGrouplessDepartures || $scope.filterOptions.hideGrouplessDepartures && tempDeparture.groups.length > 0)
                $scope.filteredDepartures.push(tempDeparture); //Add departure to filtered departures array
        }
    }

    $scope.capEditGroupsOptions = [];
    //Renew array for editing group capacity, to let user limit capacity to the same amount of pax as the most amount of pax in any of the groups that are shown
    for (i = $scope.filterOptions.largestGroup; i <= <?php echo $maxCapacity; ?>; i++) //For every capacity option possible
    {
        $scope.capEditGroupsOptions.push(i);
    }
};