1

将 BreezeJS 与 AngularJS 一起使用会出错。例如,在 ng-repeat 中使用“过滤器”时,控制台会报告:堆栈空间不足。

重现步骤

  1. 获取 Todo-Angular BreezeJS 示例并在 VS 2012 中打开。
  2. 在 index.html 之前添加<ul>


    <div>
    <input ng-model="query" type="search" placeholder="search" />
    </div>

  1. 将以下代码添加到 li 元素上的 data-ng-repeat


    <li data-ng-repeat="item in items | filter:query">

filter:query 应该根据输入中的文本过滤列表,但事实并非如此。在 IE 10 中,控制台报告“堆栈空间不足”。在 Chrome 中,控制台报告“范围错误”:

(anonymous function) angular.js:5582
(anonymous function) angular.js:4679
Scope.$digest angular.js:7739
Scope.$apply angular.js:7926
listener angular.js:11228
v.event.dispatch jquery-1.8.3.min.js:2
o.handle.u

当你使用 angular.copy(src, dest); 其中 src 是由 BreezeJS 创建的,我看到另一个 stack_overflow 错误。

4

3 回答 3

8

这是行不通的,因为您要求 Angular 将搜索文本与 TodoItem 的每个属性相匹配

Breeze 实体的属性包括entityAspect有一个称为属性的属性,该属性entity指向TodoItem实例......并且在你周围一直走,直到堆栈溢出(双关语)。

您需要使用进行特定比较的过滤器功能。试试这个:

Index.html中

<div>
  <input data-ng-model="searchText" type="Search" placeholder="search" />
</div>
<ul>
    <li data-ng-repeat="item in items | filter:itemFilter">
    ... ETC。 ...

控制器.js

$scope.searchText = "";

// 注意:这被调用了很多!
$scope.itemFilter = function (todoItem) {
    var searchText = $scope.searchText;
    // if there is search text, look for it in the description; else return true
    return searchText ?
        -1 != todoItem.Description.toLowerCase().indexOf(searchText.toLowerCase()) :
        true;
};

Works like a charm on my machine :)

p.s.: your mishap with angular.copy() has the same cause ... it does a depth copy of every property and entities tend to have circular references.

于 2013-01-31T22:09:20.893 回答
2

Ok, i implemented a custom filter, that excludes navigation properties. It just filters in the currently received breeze entity.

(function () {
'use strict';

angular.module('appFilter', []).filter('breezeFilter', function () {

    function contains(searchString, searchTerm) {
        if (!searchString) return false;
        return searchString.toString().toLowerCase().indexOf(searchTerm.toLowerCase()) != -1;
    }

    function getKeys(entity) {
        var names = [];
        var properties = entity.entityAspect.extraMetadata.properties;
        for (var property in properties) { names.push(property); }
        return names;
    }

    function search(entity, searchTerm) {
        var found = false;
        if ("entityAspect" in entity) {
            var keys = getKeys(entity);
            for (var i = 0; i < keys.length && !found; i++) {
                if (keys[i].slice(-2) !== "Id") {
                    var obj = entity[keys[i]];

                    switch (typeof obj) {
                        case 'object':
                            if (obj && !('navigationProperty' in obj)) {
                                found = search(obj, searchTerm);
                            }
                            break;
                        case 'number':
                        case 'string':
                            found = contains(obj, searchTerm);
                            break;
                        case 'boolean':
                        default:
                    }
                }
            }
        }
        return found;
    }

    return function (breezeEntities, expression) {
        if (!expression || expression.length < 2) return breezeEntities;
        var filtered = [];
        angular.forEach(breezeEntities, function (entity) {
            if (search(entity, expression)) {
                filtered.push(entity);
            }
        });
        return filtered;
    }
});
})();

I hope this helps.

于 2014-05-15T13:34:48.587 回答
0

I just had the same problem and I solved by using query projections in breeze, i.e. the "select" clause. It returns pure JavaScript object as opposed to the "wrapped" breeze entities.

于 2013-11-27T19:52:10.367 回答