简体   繁体   English

角度自定义过滤器不更新ng-repeat

[英]Angular custom filter not updating ng-repeat

There are alot of questions on here about ng-repeat and custom filters but none of them address the problem I am facing. 关于ng-repeat和自定义过滤器,这里有很多问题,但它们都没有解决我面临的问题。

Take this: 拿着它:

<div class="row" ng-repeat="row in rows | chunk:columns">

    <!-- Now loop over the row chunk to output the column -->
    <div 
        ng-class="{'col-xs-12':row.length<=1,'col-xs-6':row.length>1"
        ng-repeat="item in row"
    >
        {{ item.name }}
    </div>
</div>

The filter chunk is a custom filter that I made to return a chunk of $scope.rows that is an array of objects. 过滤器chunk是一个自定义过滤器,我返回一个$scope.rows块,它是一个对象数组。

This works fine until I change the value of $scope.columns . 这工作正常,直到我更改$scope.columns的值。 At this point I would expect the ng-repeat directive to add itself to the digest loop to re-draw but it doesn't. 在这一点上,我希望ng-repeat指令将自己添加到摘要循环中以重新绘制,但事实并非如此。

How would I get this to re-draw when the value of $scope.columns changes? $scope.columns的值发生变化时,如何重新绘制?

From comments the chunk filter is: 根据评论,块过滤器是:

var _ = require('lodash');

/**
 * Chunk an array into pieces
 * @param collection
 * @param chunkSize
 * @returns {array}
 */
var chunk = function (collection, chunkSize) 
{
    if (!collection || _.isNaN(parseInt(chunkSize, 10))) 
    { 
        return [];
    }

    return _.toArray(
        _.groupBy(collection, function (iterator, index) 
        {
            return Math.floor(index / parseInt(chunkSize, 10));
        })
    );
}

/**
 * Angular filter to cache array chunks and return
 * x number of chunks from an array via a filter.
 *
 * @example
 * <div ng-repeat="item in items | chunk:2"> ... </div>
 * @returns {array}
 */
module.exports = function()
{
    return _.memoize(chunk);

    // If I console.log(_.memoize(chunk)()) here I get the output
    // from the first digest only.
};

$scope.columns is being updated by a directive $scope.columns正在由指令更新

/**
 * toggleGridView directive
 * @returns {object}
 */
module.exports = ['localStorageService', function(localStorageService)
{
    return {
        replace : true,
        template: '<button type="button" ng-click="toggleView()"></button>',
        link : function(scope, el, attr) {
            scope.gridView = localStorageService.get('itemlistgrid') == "true";

            scope.columns = scope.gridView ? 2 : 1;

            scope.toggleView = function() 
            {
                localStorageService.set(
                    'itemlistgrid', 
                    scope.gridView = ! scope.gridView
                );

                scope.columns = scope.gridView ? 2 : 1;
            }
        }
    }
}];

The controller is in scope of the directive so I can see that columns is outputting the correct value. 控制器在指令的范围内,因此我可以看到列输出正确的值。 If I watch columns I can see it changes on update. 如果我观看columns我可以看到它在更新时发生了变化。

I removed the need for caching in the filter and moved the logic into the controller as recommended in a few other answers on questions similar to this. 我删除了过滤器中缓存的需要,并按照与此类似的问题的其他几个答案中的建议将逻辑移动到控制器中。

/**
 * Angular filter to cache array chunks and return
 * x number of chunks from an array via a filter.
 *
 * @example
 * <div ng-repeat="item in items | chunk:2"> ... </div>
 * @returns {array}
 */
module.exports = function()
{
    // Removed the _.memoize caching
    return chunk;
};

This stopped the filter working directly in the view as it was calling the filter on every iteration modifying the entire dataset that causes havok in the digest loop. 这使得过滤器直接在视图中工作,因为它在每次迭代时调用过滤器,修改导致摘要循环中出现havok的整个数据集。

I removed it and placed it directly in the controller. 我将其取下并直接放在控制器中。

// Created items as a private variable in the controller
var items = [];

// Watch for changes to gridView and call toggleGrid
$scope.$watch('gridView', toggleGrid);

function toggleGrid(flag)
{
    $scope.rows = $filter('chunk')(items, flag ? 2 : 1);
}

// With a restful resource success callback set the initial state
ItemsResource.index({}, function(data)
{
    // Set the private data to the collection of models 
    items = data.body.models;

    // Toggle the grid using the initial state of $scope.gridView
    toggleGrid($scope.gridView);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM