I need length of books that added after item, here is my controller:
$scope.items = [
{"added_days_ago": 5, "books": [{"id":1, "added_days_ago": 6}, {"id":2, "added_days_ago": 3}, {"id":3, "added_days_ago": 4}]},
{"added_days_ago": 2, "books": [{"id":4, "added_days_ago": 3}]}
]
In controller i need to define filteredBooksLength (i using ng-table) and then show like:
{{filteredBooksLength}}
Something like:
filteredBooksLength = (books where book.added_days_ago > item.added_days_ago).length
JSFiddle
$scope.filteredBooksLength = function (item) {
return item.books.filter(function (book) {
return book.added_days_ago > item.added_days_ago
}).length
Should cover your needs - summon it within the ng-repeat block, and pass in the current item - filteredBooksLength(item)
jsFiddle
How it works
We're giving the scope access to a function that accepts an item object as an argument. We take the books array on that object and pass it though a filter function, which returns only those books where book.added_days_ago is greater than item.added_days_ago as an array. We then measure the length of that array and return it.
Note on style
From what you've written - and the way you've phrased your question - it looks like you've done some Python. It's accepted practice in JS to use camelCase rather than snake_case - you may wish to change that for the the keys in your items object. In addition, the "" around those keys are superfluous.
Keep at it!
Related
I have an array (obj_values) of objects
[
#<User id: 1, name: "Kostas">,
#<User id: 2, name: "Moufa">,
...
]
And I want to convert this into an Array with only the values from above objects, so it will look like:
[
1, Kostas
2, Moufa
]
I can do it like this:
obj_table = []
obj_values.each do |ext|
ext.each do |obj|
obj_table.push([obj.id, obj.name].join(","))
end
end
However with this approach I need to explicitly specify what attributes I want to push (obj.id and obj.name), is there a way to push whole data from object without the need to specify each attribute separately?
Use .attributes to get a hash of all the attributes on the model. Call .values on it to get just the values without the keys.
Using your code:
obj_table = []
obj_values.each do |ext|
ext.each do |obj|
obj_table.push(obj.attributes.values.join(","))
end
end
Though there are better ways. I suggest you look into .map and .flat_map.
obj_table = obj_values.flat_map do |ext|
ext.map do |obj|
obj.attributes.values.join(",")
end
end
Yes, you can push data without specifying it separately. to push data you have to use an object.attributes.values
an object will be your active record object.
attributes will return a hash with all attributes of that object.
so you can change your loops into a single statement like:
obj_values.flat_map {|object_value| object_value.attributes.values }
I'm working in a real-time web application for my company, and I'm using MEAN stack with socket.io to provide real-time $scope variable updates in all clients in a specific socket room.
I'm currently using an array of objects that is dynamic, being able to add or remove elements, and I have to set a $watch function for each array element and pass the element's _id in it's respective $watch function. The problem is: AngularJS can't keep track of element's position in array by it's _id as elements are removed.
So I was considering, instead of using an array to store objects, use an object with unique properties that are each element's id, like this:
$scope.mainObj = {
'1234': {name: 'bob', age: 21},
'1235': {name: 'william', age: 23},
'1236': {name: 'rob', age: 28}
};
instead of:
$scope.mainArray = [
{_id: '1234', name: 'bob', age: 21},
{_id: '1235', name: 'william', age: 23},
{_id: '1236', name: 'rob', age: 28}
];
At first, I think this would remove the problem of having to index my array and having to locate the element's position in every client in a room to update a variable, making the changes atomic by updating the property named after element's _id.
Would this bring any performance issue or another problem? Like I said, array indexes would be dispensable, lookup functions to detect the element by _id wouldn't be necessary and the chances of updating the wrong element would be 0, as using the indexed array approach exists a minimal chance of the wrong element be updated when too many users are adding, removing or editing array elements.
So, is it a good idea? If not, how could I $watch array elements, pass the element _id in watch function and don't lose track of each element? What I have now is this:
$scope.setWatch = function (element, id) {
$scope.$watch(x, function() {
console.log('watching: ' + element);
console.log('do something with : ' + id);
});
}
socket.on('addArrayElm', function (res) {
var id = res.id;
$scope.mainArray.push(new arrayElement(id));//creates new element from constructor with received _id from server
$scope.mainArrayIndex.push(id);//push id in index array
var i = $scope.mainArrayIndex.length - 1;//get the pushed element index in array
var j = 'mainArrayIndex[' + i + '].name';//construct string to use in $watch function referring to the element in array's position 'i'
$scope.setWatch(j, z);
$scope.$apply();
});
The main problem is: if I remove an element, like the second one (index = 1), the $watch function is not destroyed, and as it took the index = 1 as a parameter, it's going to be triggered for the element that took index = 1, so the wrong _id is used.
What should I do?
Thanks!
I'm passing an array to the jade document. Then I'd like to access the values of the array via a variable to keep the markup simple. Just see the example below. I have already picked up, that the jade syntax can be quite strange dealing with arrays (stuff like "arr.[0]"). Can you guys tell me what im overseeing here? Big thanks!
- var arr = [
{
name: 'foo',
id: 1
},
{
name: 'bar',
id: 2
}
]
- var item = arr[0];
h2 #{item.id} // doesn't work
h2 #{arr[0].id} // works
h2 #{arr[0].id}
Works because you are referencing the id for arr item in the '0' (first) position. This is because the array starts counting things with a zero, not a one.
As you can probably see from your results, this code would return '1', which means that you could expect h2 #{arr[0].name} To return 'foo'.
To get the ids from both items in the array 'arr', change your code to this.
h2 #{arr[0].id}
h2 #{arr[1].id}
I'd like to get some models in my collection that have the attribute unit. My current method involves this,
var unitIds = ciLocal.where({unit: !null});
console.log(unitIds.length);
The weird thing is that removing ! returns 58 (the total minus those that unit is not null) values while the code above returns 0.
Can anyone suggest a good way to loop my collection and return those models that have anything in unit?
Its probably worth mentioning that unit contains two values, one being unitID and the other being an array of more values. I need to get the whole model back and not just the unit section.
In this screenshot you can see that 68 has null while 69 has object.
{"carID":"37","unit":{"unitID":"37_Chaffinch_75","positionHistory":[{"lat":"51.474312","long":"-0.491672","time":"2011-07-08 11:24:47","status":"1","estimatedSpeed":"0","lastSoundFileName":"Car park Exit","lastSoundRange":"10","lastSoundTime":"2011-07-08 11:25:03","isToday":false,"minutesAgo":1028188}]},"registration":"CJ-361-YG","color":"Luxor","phone":"","model":"SDV8"}
You can use _.filter on your collection to specify a custom validation function.
filter _.filter(list, iterator, [context])
Looks through each value in the list, returning an array of all the values that pass
a truth test (iterator).
Something like this should keep the models with a defined, non null value
var c = new Backbone.Collection([
{id: 1, unit: 1},
{id: 2, unit: null},
{id: 3}
]);
c.filter(function(model) {
var v = model.get('unit');
return ((typeof(v)!=='undefined') && (v!==null));
})
And a demo http://jsfiddle.net/nikoshr/84L2R/
I'm having trouble getting the sortedIndex underscore method to return a useful value. I have a collection with a comparator, and that's adding models correctly in order. I would just like to know the potential index of a new model, and the sortedIndex method is return 0 matter what I try.
var Chapter = Backbone.Model;
var chapters = new Backbone.Collection;
chapters.comparator = function(chapter) {
return chapter.get("page");
};
chapters.add(new Chapter({page: 9, title: "The End"}));
chapters.add(new Chapter({page: 5, title: "The Middle"}));
chapters.add(new Chapter({page: 1, title: "The Beginning"}));
var foo = new Chapter({ page: 3, title: 'Bar' });
// Will always return 0 no matter the value of page in foo.
console.log(chapters.sortedIndex(foo));
I know there's something wrong in there, or perhaps that's no the intention of sortedIndex but I'm unsure either way.
The problem is Underscore.js knows nothing about the comparator function of the collection and expects comparator as an argument of sortedIndex function. This will work as expected:
console.log(chapters.sortedIndex(foo, chapters.comparator));