Selecting dynamically created models within a collection - backbone.js

I have a set of "Person name" inputs with the class person that I'm trying to do the following with: each time a keyup is recorded in the input, grab that input's data-hash attribute, and if there's not already an instance of Person with that hash in the collection People, add a model. Otherwise just update the model where hash matches.
$('.person').keyup(function(){
var myHash = $(this).attr('data-hash'),
myName = $(this).val(),
checkMe = people.where({'hash':myHash});
if ( checkMe.length > 0 ){
//update name value where hash matches
}
else {
people.add({
'name':myName,
'hash':myHash
});
}
});
Instead of using var person = new Person I'm adding these models to the collection using Backbone's add method.
So now I have a number of elements when I call people.models but I can't figure out how to select them. Normally you'd say person.get('attribute') but I'm not sure how to select the model if it has no var name. What could I put in the code instead of //update name value where hash matches?

checkMe should be an array of models you're trying to update. Iterate through them and use the set method:
$('.person').keyup(function(){
var myHash = $(this).attr('data-hash'),
myName = $(this).val(),
checkMe = people.where({'hash':myHash});
if ( checkMe.length > 0 ){
_.each(checkMe, function(person){
person.set({
'name':myName,
});
});
}
else {
people.add({
'name':myName,
'hash':myHash
});
}
});

Related

AngularJS server-side multi-column search

I am building an application in NodeJS and AngularJS.
I am building a multi-column search functionality where the user can type in search keywords into separate searchboxes (at the top of each column) and retrieve the results based on the column.
So far I have a single searchbox that searches all attributes at the same time.
How can I implement multiple individual searchboxes that will return results based on multiple attributes?
Note: I want to implement this on the server-side for performance reasons. (I know that I can simply use HTML attributes | filter:column1 | filter:column2 but want to avoid this technique if possible).
Here is the code I have so far. I am thinking that I need to pass in some sort of "searchBy" variable that is set on the view and then update the search method to search by multiple query/attribute pairs.
//Search service factory
//Initialize filtered items and get search results
function search(items, query) {
this.filteredItems = $filter('filter')(items, function (item) {
for(var attr in item) {
if (searchMatch(item[attr], query))
return true;
}
return false;
});
return this.filteredItems;
}
function searchMatch(haystack, needle) {
if (!needle) {
return true;
}
return haystack.toString().toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};
//Controller
vm.filteredItems = vm.search(vm.unfilteredItems, vm.query);
//View
input(type='text', ng-model='vm.query', ng-change='vm.search(vm.unfilteredItems, vm.query)', placeholder='Search')
I was able to solve this by first creating an array of objects for each search box then repeating those boxes in the view with the ng-repeat attribute.
//Controller
var vm = this;
var vm.unfilteredItems; //data source query removed for brevity
//Initialize search inputs
vm.search_by_inputs = [
{search_column: 'id', search_query: ''},
{search_column: 'requester', search_query: ''},
{search_column: 'dataowner', search_query: ''}
];
function initSearch() {
vm.filtered_items = vm.search(vm.unfiltered_items, vm.search_by_inputs);
}
//View
input.input-large.search-query(type='text', value='{{search_by.search_query}}', ng-model='search_by.search_query' ng-change='vm.initSearch()', placeholder='Search')
The next step is to loop over the search_by_inputs object in the controller and create a new object with only the inputs that have search values entered into the searchboxes in the view. Then in the search method the built-in "filter" component iterates each item, and inside that loop each of the search terms is checked against that value with the column name that matches the property.
/*
* Create new array of objects with only elements that have search values to optimize loop inside filter
* #search_by_inputs array of objects each has a key search_column and a value search_query
*/
function optimizeSearchProperties(search_by_inputs) {
search_by_properties = [];
for (var i = 0, len = search_by_inputs.length; i < len; i++) {
//If this column input box has query text
if (search_by_inputs[i].search_query) {
search_by_properties.push(search_by_inputs[i]);
}
}
return search_by_properties;
}
/*
* #haystack search item
* #needle search term
*/
function searchMatch(haystack, needle) {
if (!needle) {
return true;
}
return haystack.toString().toLowerCase().indexOf(needle.toLowerCase()) !== -1;
}
/*
* Create filtered items object by filtering search results
* #items original array of objects returned by database query result
* #search_by_inputs array of objects each has a key search_column and a value search_query
*/
function search(items, search_by_inputs) {
var search_by_properties = optimizeSearchProperties(search_by_inputs);
//If there are no search properties input by requester then return all items
if (search_by_properties.length === 0) {
this.filtered_items = items;
return this.filtered_items;
}
this.filtered_items = $filter('filter')(items, function (item) {
var search_result = true;
//Loop over all search by input textboxes
for (var n = 0, len = search_by_properties.length; n < len; n++) {
//If there is no query text
if (!search_by_properties[n].search_query) {
//Continue to next element in array
continue;
//Else if element has a property that matches search input column name
} else if (item[search_by_properties[n].search_column]) {
if (!searchMatch(item[search_by_properties[n].search_column], search_by_properties[n].search_query)) {
search_result = false;
break;
}
}
}
return search_result;
});
return this.filtered_items;
}
I would be glad to have some feedback on this solution in terms of optimization, performance, technique, etc. Thanks!

Doc with ObjectId Array - push value if exists, remove otherwise

I'm new to MongoDB and mongoose.
So my model holds many fields, amongst them is an Array of ObjectIDs
var modelSchema = new Schema({
//...
inner_array: [Schema.Types.ObjectId],
//...
});
What I'm trying to achieve with my query is:
Find a model by it's Id,
If the inner array contains a specific value remove it from the array.
If the value is not within the inner_array, push it
var target_id = // document id
var inner_object_id = // value to push
models.MyModel.findOne(
{_id: target_id},
function (err, model) {
// IN THIS SCOPE 'INNER_OBJECT_ID' IS UNDEFINED
// if model.inner_array contains 'inner_object_id', remove it
// otherwise, push 'inner_object_id' into model.inner_array
model.save();
res.json(model); // return modified document to client
}
);
I believe this can be written in a single findOneAndUpdate, but I can't figure out the syntax..
Thanks alot!
I believe you can achieve that using MongooseArray.pull and MongooseArray.addToSet
var target_id = // document id
var inner_object_id = // value to push
models.MyModel.findOne({
_id: target_id
}, function (err, model) {
if (model.inner_array.indexOf(inner_object_id) !== -1) {
model.inner_array.pull(inner_object_id);
} else {
model.inner_array.addToSet(inner_object_id);
}
model.save();
res.json(model); // return modified document to client
}

Creating nested array in firebase Object

I want to push a value to a nested array which is stored in my firebase database. The target looks like this:
I'm query the firebase database and receive snapshot. With this snapshot I want to store my changes. If i push the new value it creates me in firebase this:
How can I avoid the unique FB id and replace it with a normal index counter?
My code from the angular service:
//Save StarBewertung on Mamis
this.saveStarOnMami = function (data) {
var ref = new Firebase("https://incandescent-heat-5149.firebaseio.com/contacts")
var query = ref.orderByChild("id").equalTo(data).on("child_added", function(snapshot) {
if( snapshot.val() === null ) {
/* does not exist */
} else {
//snapshot.ref().update({"phone_fixed": '123'});
snapshot.ref().child('rateData').push(1);
}
});
}
Is there a way to get the snapshot as an $firebaseobject, manipulate it, and then save it to the Firebase DB with $save?
Thanks...
dbRef.push() will always append the data with a new UID as key.
Use dbRef.update() or dbRef.set() instead.
Example (untested)
var rateSnapshot = snapshot.child('rateData');
if( rateSnapshot.val() === null ) { // rateData key does not exist
rateSnapshot.ref().set([5]);
} else {
var rates = rateSnapshot.val(); //should be an array
rates.push(1); //append new value to the array
rateSnapshot.ref().set(rates);
}

How to replace the property of the object dynamically in angualrjs?

var $scope.form = {
Name: "",
fields: []
}
angular.forEach($scope.form.fields, function (f) {
if (f.hasOwnProperty('order')) {
//code to replace the value of the property
} else {
//if order is not present push the new values to the $scope.form.fields.
}
});
I have a pop up their I am appending textboxes.When i append one text box,I am pushing the object to $scope.form.fields i.e.,Name,id,order..When i append the second textbox it is itering 2 times and getting 3 textboxes displayed. Its getting doubled for every new textbox.So I thought when $scope.form.fields contains order i should have a right to change the name of the textbox.If its not present i'l just push those new object into $scope.form.fields.Can anyone give a solution for it .
As I can see you're having an array ie fields and you need to push the new values when array doesn't already contain the same. You can use either indexOf or inArray functions of array. Try below snippet
angular.forEach($scope.form.fields, function (f, key) {
if (f.indexOf('order') >= 0) { // check whether array contains `order` or not
$scope.form.fields[key]['order'] = 'new value';
} else {
$scope.form.fields.push('new value');
}
});

Storing a list of Items in Cookie in Angular

im am trying to store a list of items in a cookie.
For Testing-Examples i use a list of citys.
It works so far but i always get the
SQLiteManager_currentLangue: and the XSRF-TOKEN: with it.
I dont really have an idea how to get rid of them both.
Any suggestions?
$scope.addToList = function(name,id) {
var cityToAdd = name;
var cityToAddID = id;
// ADD A CITY TO THE COOKIE -> WORKS
$cookies.put(cityToAddID, cityToAdd);
// SHOW THE NEW CITY_LIST ->WORKS
var allCitys = $cookies.getAll();
console.log(allCitys);
// PUT ALL INTO AN ARRAY -> WORKS
var favouritesFromCookie = [];
$.each(allCitys, function(index, value) {
console.log(value);
favouritesFromCookie.push(value);
});
// PUT THE ARRAY OF CITYS INTO A SCOPE_VARIABLE
$scope.favouriteFinal = favouritesFromCookie;
// GET RID OF THE LAST TWO ELEMENTS
}
You could give your own cookies a recognizable label and then grab that conditionally when you're compiling your array. Like so:
$cookies.put('city.' + cityToAddID, cityToAdd);
...
$.each(allCitys, function(index, value) {
if (index.indexOf('city.') == 0) { favouritesFromCookie.push(value) }
});

Resources