Find model which doesnt have an attribute in Backbone collection - javascript

I know that we can find all models in collection like so, based on attributes
var friends = new Backbone.Collection([
{name: "Athos", job: "Musketeer"},
{name: "Porthos", job: "Musketeer"},
{name: "Aramis", job: "Musketeer"},
{name: "d'Artagnan"},
]);
friends.where({job: "Musketeer"});
However i want to find the model which doesn have the attribute, or the key. How to do it?
Something like
friends.where(not(job));
Any help is greatly appreciated

Backbone provide wide range of underscore methods for Backbone.Collection instances. One of such method is Backbone.Collection.filter which filters models in collection based on the result of a custom function. Here is an example of how it could be used:
var friends = new Backbone.Collection([
{name: "Athos", job: "Musketeer"},
{name: "Porthos", job: "Musketeer"},
{name: "Aramis", job: "Musketeer"},
{name: "d'Artagnan"},
]);
friends.filter(function(model) {
return _.isUndefined(model.get('job'));
});
JSFiddle for the code above: https://jsfiddle.net/Ljve5104/

I would try something like this, being friends a backbone collection.
function isMusketeer() {
return friend.get('job') && friend.get('job') === "Musketeer";
}
function hasNoJob() {
return !friend.get('job');
}
friends.find(hasNoJob); //The first without a job
friends.find(isMusketeer); //The first that is a musketeer
friends.filter(hasNoJob); // List of results that has no job
friends.filter(isMusketeer); // List of results that are musketeer
I just separate the criteria / predicates , and then applied to the collections underscore function you need, in this case can be for many results or one result, depending on your needs.

Related

Restructure an array of objects in JS so key and value pairs match

I have an array with objects like this
[
{name: 'Donegal', code: 'DL'},
{name: 'Dublin', code: 'DUB'},
{name: 'Meath', code: 'MH'}
]
How do I restructure it so it looks like this
[
{Donegal: 'Donegal'},
{Dublin: 'Dublin'},
{Meath: 'Meath'}
]
**** EDIT ****
Apologies, but after receiving feedback, I looked at my question again and realized that I wrote the desired object incorrectly, apologies for that. Regardless, the question has been answered (Thank you everyone for your comments and answers). For the record, here is the desired output
[
{
Donegal: 'Donegal',
Dublin: 'Dublin',
Meath: 'Meath'
}
]
The structure you are targeting looks wrong: having an array with little objects that have one dynamic property, kills any benefit you would have from using object keys.
Instead go for one object (not an array):
let input = [
{name: 'Donegal', code: 'DL'},
{name: 'Dublin', code: 'DUB'},
{name: 'Meath', code: 'MH'}
];
let output = Object.fromEntries(
input.map(({name}) => [name, name])
);
console.log(output);

I have a collection of items. Based on the two data points, I need to query that items

I have a collection of items. Based on the two data points, I need to filter out that items. As an example: I have a collection of action objects [{name: Detail}, {name: Spec}...] and I have two data points like I am category 'G' and in page 'A' would use only Detail action but I am category 'G' but in page 'B' only use Spec action and etc. What is the best OOP approach for this problem to scale to 100 of actions and base that on 10 of category and pages? I have tried to solved with Factory pattern but it did not work out.
The simplest solution is to create mapping of pages and allowed actions for this page.
Example:
const actions = [{name: 'Detail'}, {name: 'Spec'}];
const pages = [
{
name: 'A',
allowedActions: [{name: 'Detail'}]
},
{
name: 'B',
allowedActions: [{name: 'Spec'}]
}
]
const getAllowedActions = pageName => {
return pages.find(page => page.name == pageName).allowedActions;
}
console.log(getAllowedActions('A'));
Out:
[ { name: 'Detail' } ]

Return a backbone model if the model contains a key that exists using findWhere

I am trying to use findWhere to find out if a collection has a model that contains a specific key (which if it exists will be an object). I only want to know if the collection contains this criteria.
Here is a sample collection:
var collection = new Backbone.Collection([
{name: "Tim", age: 5},
{name: "Ida", age: 26, schools: {elementary: "School One", middle_school: "School Two"} },
{name: "Rob", age: 55}
]);
How would I determine if this collection has a model that has the key schools with findWhere? Is there a faster way of determining this?
findWhere() doesn't work like that. I'd use find() or some():
collection.find(function (model) {
return model.has('schools');
});
It will return the first model that passes the test (or undefined). If you don't care about the model you can just test the return value for truthiness, or you can use some() instead:
collection.some(function (model) {
return model.has('schools');
});
It'll return true if a model passes the test. Of course they don't document what it returns if nothing passes the test.
See the documentation on Collection : Underscore Methods for more info.

One JSON object into few collection objects

I'm having a puzzler here. I have the following collection:
var TagsCollection = Backbone.Collection.extend({
model: TagModel,
parse : function(response) {
console.log(response);
// code to go
return response;
}
});
Now that fetches the following sample JSON object:
{
id: 10149682,
published: "2014-01-13 08:23:00",
title: "Title",
tags: "tag1,tag2,tag3,tag4"
}
now what I want is to insert some code that will re-map the existing response into the following format:
[{name: "tag1"}, {name: "tag2"}, {name: "tag3"}, {name: "tag4"}]
and load it into the collection. (An important note - using Backbone / Underscore methods - for ex. _.chain / _.reduce etc.).
You can split you tags key:
var tags = response.tags.split(',');
And map the resulting array
return _.map(tags, function(tag) {
return {name: tag};
});
You can also try something like:
var tags= "tag1,tag2,tag3,tag4";
var newArr = tags.split(',').map(function(tag){ return {name: tag} });
Important: This works in IE9+ if you need this to run in IE8 or older you need to polufill. You can fine the instructions here

How to use parameters within the filter in AngularJS?

I want to use parameter in filter, when I iterate some arrays with ng-repeat
Example:
HTML-Part:
<tr ng-repeat="user in users | filter:isActive">
JavaScript-part:
$scope.isActive = function(user) {
return user.active === "1";
};
But I want to be able to use filter like
<tr ng-repeat="user in users | filter:isStatus('4')">
But its not working. How can I do something like that?
UPDATE: I guess I didn't really look at the documentation well enough but you can definitely use the filter filter with this syntax (see this fiddle) to filter by a property on the objects:
<tr ng-repeat="user in users | filter:{status:4}">
Here's my original answer in case it helps someone:
Using the filter filter you won't be able to pass in a parameter but there are at least two things you can do.
1) Set the data you want to filter by in a scope variable and reference that in your filter function like this fiddle.
JavaScript:
$scope.status = 1;
$scope.users = [{name: 'first user', status: 1},
{name: 'second user', status: 2},
{name: 'third user', status: 3}];
$scope.isStatus = function(user){
return (user.status == $scope.status);
};
Html:
<li ng-repeat="user in users | filter:isStatus">
OR
2) Create a new filter that takes in a parameter like this fiddle.
JavaScript:
var myApp = angular.module('myApp', []);
myApp.filter('isStatus', function() {
return function(input, status) {
var out = [];
for (var i = 0; i < input.length; i++){
if(input[i].status == status)
out.push(input[i]);
}
return out;
};
});
Html:
<li ng-repeat="user in users | isStatus:3">
Note this filter assumes there is a status property in the objects in the array which might make it less reusable but this is just an example. You can read this for more info on creating filters.
This question is almost identical to Passing arguments to angularjs filters, to which I already gave an answer. But I'm gonna post one more answer here just so that people see it.
Actually there is another (maybe better solution) where you can use the angular's native 'filter' filter and still pass arguments to your custom filter.
Consider the following code:
<li ng-repeat="user in users | filter:byStatusId(3)">
<span>{{user.name}}</span>
<li>
To make this work you just define your filter as the following:
$scope.byStatusId = function(statusId) {
return function(user) {
return user.status.id == statusId;
}
}
This approach is more versatile because you can do comparisons on values that are nested deep inside the object.
Checkout Reverse polarity of an angular.js filter to see how you can use this for other useful operations with filter.
If you have created an AngularJs custom filter, you can send multiple params to your filter.Here is usage in template
{{ variable | myFilter:arg1:arg2... }}
and if you use filter inside your controller here is how you can do that
angular.module('MyModule').controller('MyCtrl',function($scope, $filter){
$filter('MyFilter')(arg1, arg2, ...);
})
if you need more with examples and online demo, you can use this
AngularJs filters examples and demo
This may be slightly irrelevant, but if you're trying to apply multiple filters with custom functions, you should look into:
https://github.com/tak215/angular-filter-manager
Example I have a students list as below :
$scope.students = [
{ name: 'Hai', age: 25, gender: 'boy' },
{ name: 'Hai', age: 30, gender: 'girl' },
{ name: 'Ho', age: 25, gender: 'boy' },
{ name: 'Hoan', age: 40, gender: 'girl' },
{ name: 'Hieu', age: 25, gender: 'boy' }
];
I want to filter students via gender to be boy and filter by name of them.
The first I create a function named "filterbyboy" as following:
$scope.filterbyboy = function (genderstr) {
if ((typeof $scope.search === 'undefined')||($scope.search === ''))
return (genderstr = "")
else
return (genderstr = "boy");
};
Explaination: if not filter name then display all students else filter by input name and gender as 'boy'
Here is full HTMLcode and demo How to use and operator in AngularJs example

Categories