AngularJS - 基于父ng-repeat在ng-repeat中排序和解析数据

时间:2014-05-21 10:38:38

标签: jquery angularjs angularjs-directive angularjs-scope angularjs-ng-repeat

我试图编写一个相当复杂的ng-repeat,可能会使用过滤和解析。

我首先要做的是ng-repeat从当月起12个月的表格。

然后我显示两行 - 有影响力的搜索没有影响的搜索

我要做的是循环浏览包含我的搜索数据的JSON文件,并计算有多少带有影响的搜索无影响搜索的数量根据 SearchedOn 字段为该特定月份执行。

理解具有影响力的搜索无影响搜索背后的逻辑基于 IsIncludedInSearchImpactCalculation 字段为true或false。

还需要发生的是,如果我的JSON文件包含大于12个月的数据元素(基于 SearchedOn 字段),那么这应该不包括在计算中。 / p>

HTML:

<div ng-app="test">
    <div ng-controller="Ctrl">
        <table>
            <thead>
                <tr>
                    <th></th>
                    <th ng-repeat="currMonth in months">{{currMonth}}</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th>Searches with impact</th>
                    <td></td>
                    <td>3</td>
                    <td></td>
                    <td>1</td>
                    <td>1</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td>3</td>
                    <td>1</td>
                    <td></td>
                    <td>1</td>
                </tr>
                <tr>
                    <th>Searches with NO impact</th>
                    <td>2</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </tbody>
        </table>
        <br>
        <p>Searches with impact:</p>
        <li ng-repeat="searchedOn in Searches | filter:{IsIncludedInSearchImpactCalculation:true}">{{searchedOn.SearchedOn}}</li>
        <br>
        <p>Searches with NO impact:</p>
        <li ng-repeat="searchedOn in Searches | filter:{IsIncludedInSearchImpactCalculation:false}">{{searchedOn.SearchedOn}}</li>
    </div>
</div>

JS:

angular.module('test', []).controller('Ctrl', function ($scope) {
    var date = new Date();
    var months = [],
        monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    for (var i = 0; i < 12; i++) {
        months.push(monthNames[date.getMonth()] + ' ' + date.getFullYear());

        // Subtract a month each time
        date.setMonth(date.getMonth() - 1);
    }
    $scope.months = months;



    $scope.Searches = [{
        "SearchedOn": "19/04/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "18/04/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "01/05/2014",
            "IsIncludedInSearchImpactCalculation": false
    }, {
        "SearchedOn": "21/05/2014",
            "IsIncludedInSearchImpactCalculation": false
    }, {
        "SearchedOn": "20/07/2013",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "07/01/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "08/12/2013",
            "IsIncludedInSearchImpactCalculation": false
    }, {
        "SearchedOn": "24/02/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "30/06/2013",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "28/06/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "14/08/2013",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "11/04/2014",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "13/08/2013",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "03/08/2013",
            "IsIncludedInSearchImpactCalculation": true
    }, {
        "SearchedOn": "20/01/2011",
            "IsIncludedInSearchImpactCalculation": true
    }];
});

这是我的小提琴:http://jsfiddle.net/oampz/j9LBe/

在我的小提琴中,我根据列表手动硬编码了表格的样子。


更新

添加:

<td ng-repeat="item in filtered = (Searches | filter:{IsIncludedInSearchImpactCalculation:true})"></td>
                <td>Filtered list has {{filtered.length}} items</td>

获取带有影响的搜索无影响的搜索的行中的项目总数,请参阅小提琴:http://jsfiddle.net/oampz/j9LBe/1/

现在所需要的只是根据之前的ng-repeat分组:

 <th ng-repeat="currMonth in months">{{currMonth}}</th>

3 个答案:

答案 0 :(得分:1)

试试这个

<强>脚本

<强> Working Demo

var months = [],
        monthNames = [{ monthNo: 1, monthName: "Jan" },
                      { monthNo: 2, monthName: "Feb" },
                      { monthNo: 3, monthName: "Mar" },
                      { monthNo: 4, monthName: "Apr" },
                      { monthNo: 5, monthName: "May" },
                      { monthNo: 6, monthName: "Jun" },
                      { monthNo: 7, monthName: "Jul" },
                      { monthNo: 8, monthName: "Aug" },
                      { monthNo: 9, monthName: "Sep" },
                      { monthNo: 10, monthName: "Oct" },
                      { monthNo: 11, monthName: "Nov" },
                      { monthNo: 12, monthName: "Dec" }];

    for (var i = 0; i < 12; i++) {
        var obj = {};
        obj.month = monthNames[date.getMonth()];
        obj.year = date.getFullYear();
        months.push(obj);
        // Subtract a month each time
        date.setMonth(date.getMonth() - 1);
    }

<强> HTML

<th ng-repeat="curr in months|orderBy:'month.monthNo'">{{curr.month.monthName}}  {{curr.year}}</th>

答案 1 :(得分:1)

<强> Fiddle Here

它简单地归结为这个过滤器:

$scope.searchFilter = function(included,date){
    return function(search){
        if(search.IsIncludedInSearchImpactCalculation!==included) return false;

        //needed to parse and use date constructor on your json's dates
        var dateParts = search.SearchedOn.split("/");
        var searchedOn = new Date(dateParts[2],dateParts[1]-1,dateParts[0]);//months are 0-11

        if(date.month === searchedOn.getMonth() && date.year===searchedOn.getFullYear()) return true;
        else return false;
    };
}

并像这样使用它:

<th>Searches with impact</th>
      <td ng-repeat="currMonth in months">{{(Searches|filter:searchFilter(true,currMonth)).length}}</td>

或者这个:

<th>Searches with NO impact</th>
      <td ng-repeat="currMonth in months">{{(Searches|filter:searchFilter(false,currMonth)).length}}</td>

这基本上是你在标题中提出的,基于父循环(ng-repeat月)解析和过滤内循环中的数据(由| filter传递每个数组元素到函数。)

基本上我们需要再次ng-repeat个月,但这次是为每个月打印已包含和未包含的搜索计数。所以我们的过滤器需要3个参数,首先是它是否包括在内,第二个是有问题的月份,最后是检查匹配月份的搜索。

angular filters希望数组过滤并将每个项目传递给过滤器函数。所以我们返回一个函数,将单个搜索作为参数,做我们的事情并返回true或false,具体取决于它是否符合我们的标准。

结果| filter返回一个新数组,其中填充了一些从过滤函数返回true的数组(这样我们就可以ng-repeat使用过滤器等)。由于我们现在有匹配的数组,我们可以简单地计算它的长度。

我知道这听起来有些令人困惑,但要检查一下它并不像我解释的那样令人困惑。

随意提出任何不清楚的事情。

答案 2 :(得分:1)

<强> Working Demo - JSFiddle

<强>脚本:

检索过去12个月并将其存储在数组中。请注意,我们存储了一个对象文字数组(年,月,值)。

      function getMonths() {
            var date = new Date();

            var months = [];

            for (var i = 0; i < 12; i++) {
                months.push({
                    year: date.getFullYear(),
                    month: date.getMonth()+1,
                    value: new Date(date.getFullYear(), date.getMonth(), 1)
                });

                // Subtract a month each time
                date.setMonth(date.getMonth() - 1);
            }

            return months;
        }

        $scope.months = getMonths();

定义搜索过滤器。这些搜索过滤器将用于按搜索影响缩小搜索结果范围,并按月对结果进行分组。 'count'过滤器是返回结果计数的最终过滤器。

按搜索影响过滤:

   app.filter('bySearchImpact', function() {
        return function(input, isIncludedInSearchImpact) {
            var output = [];
            for (var i in input) {
                if (input[i].IsIncludedInSearchImpactCalculation == isIncludedInSearchImpact) {
                    output.push(input[i]);
                }
            }

            return output;
        }
    });

按月过滤:

    app.filter('byMonth', function () {

        function isSameMonth(date1, date2) {
            var month1 = date1.split('/')[1];
            var year1 = date1.split('/')[2];
            return parseInt(year1) == date2.year &&
                parseInt(month1) == date2.month;
        }
        return function (input, month) {

            var output = [];
            for (var i in input) {
                if (isSameMonth(input[i].SearchedOn, month)) {
                    output.push(input[i]);
                }
            }

            return output;
        };

    });

计数过滤器:

    app.filter('count', function() {
        return function(input) {
            return input.length;
        };
    });

<强> HTML:

现在我们有了SearchImpact和Month过滤的过滤器,以及用于返回计数的过滤器,我们可以应用它们来获得最终结果:

显示表标题(注意我们如何使用Angular的日期过滤器)

 <th ng-repeat="month in months">{{month.value | date: 'MMM yyyy' }}</th>

使用影响进行搜索:

 <td ng-repeat="month in months">{{Searches | bySearchImpact:true | byMonth:month | count}}</td>

没有影响的搜索:

 <td ng-repeat="month in months">{{Searches | bySearchImpact:false | byMonth:month | count }}</td>

显示具有影响力的搜索日期:

<li ng-repeat="searchedOn in Searches |  bySearchImpact:true">{{searchedOn.SearchedOn}}</li>

显示没有影响的搜索日期:

<li ng-repeat="searchedOn in Searches | bySearchImpact:false">{{searchedOn.SearchedOn}}</li>