Reputation: 108
Using BreezeJS with AngularJS gives errors. For example when using 'filter' in an ng-repeat the console reports: running out of stack space.
Steps to reproduce
<ul>
<div>
<input ng-model="query" type="search" placeholder="search" />
</div>
<li data-ng-repeat="item in items | filter:query">
The filter:query should filter the list based upon the text in the input but it doesn't. In IE 10 the console reports "running out of stack space". In Chrome the console reports"Range Error":
(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
When you use angular.copy(src, dest); where src is created by BreezeJS I see another stack_overflow error.
Upvotes: 1
Views: 1680
Reputation: 2200
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.
Upvotes: 2
Reputation: 1663
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.
Upvotes: 0
Reputation: 17863
That won't work because you're asking Angular to match the search text to every property of the TodoItem.
A Breeze entity's properties include the entityAspect
which has a property called entity
that points back to the TodoItem
instance ... and around you go until the stack overflows (pun intended).
You need to use a filter function that does specific comparisons. Try this:
In Index.html
<div> <input data-ng-model="searchText" type="Search" placeholder="search" /> </div> <ul> <li data-ng-repeat="item in items | filter:itemFilter"> ... etc. ...
In controller.js
$scope.searchText = ""; // Beware: this is called a lot! $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.
Upvotes: 8