save multiple record in backbone model? - javascript

Am trying to save model in backbone. This code is working
myModel.save({'title':title},{changed:'title'});
But am not sure why it is not working without changed attribute. myModel.save({'title':title});
Also how do I save multiple records using this?

To save multiple attributes for a single model, include all the changed attributes and their corresponding values in a single object {}.
For example:
myModel.save({
attributeA: valueA,
attributeB: valueB,
attributeC: valueC
});
It may help to read through backbone's annotated source regarding the save function.
To save attributes on all models in a collection, you could iterate over the collection, possibly using underscore's each function.
For example:
myCollection.each(function (myModel) {
myModel.save({
attributeA: valueA,
attributeB: valueB,
attributeC: valueC
});
})
Note: Since these examples are out of context, unique values for the attributes would have to be handled with additional logic.

Related

Append to an arary field in Firestore

I'm using Firebase and Vuejs to create an database element, which has object array inside.
That's how the field looks, and I want to add tasks through the form into the 'moreTasks' as an array.
I tried using this, but it just creates new entity in the database.
db.collection('Tasks').add({
tasker: this.tasker.taskerName
})
I also tried checking API but I couldnt understand the refs, because I was using different methods to achieve that goal.
creatTask() {
db.collection('Tasks').add({
task_id: this.task_id,
name: this.name,
What would be correct way to approach this problem?
You can append an item to an array using FieldValue.arrayUnion() as described in the documentation. For example:
// Atomically add a new region to the "regions" array field.
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});
The accepted answer used to be correct but is now wrong. Now there is an atomic append operation using the arrayUnion method:
https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array
This is true as long as you are using firestore and not real time db (which I assume is the case from the tags)

Update key in Firebase

I've been going through the docs, but I don't see a way to update a value at a specific key (while keeping the rest). Is the only way to achieve this is to fetch the existing data and overwrite it using set()?
I have something like this:
firebase.database()
.ref(`/users/${currentUser.uid}/products/${productKey}`)
.set({category: name});
where products have many other key-value pairs, and using set() overwrites the entire object, which is not what I want in this case.
I appreciate any help!
From the section Update specific fields:
To simultaneously write to specific children of a node without overwriting other child nodes, use the update() method.
In your snippet that would be:
firebase.database()
.ref(`/users/${currentUser.uid}/products/${productKey}`)
.update({category: name});

Knockout mapping plugin [create, update]: objects created, cannot update

I've posted my code here: http://jsfiddle.net/HYDU6/6/
It's a pretty stripped-down version of what I'm actually working with, but captures the essence of my problem. My view model is like so:
var viewModel = {
objects: {
foo: [
{ text: "Foo's initial" },
],
bar: [
{ text: "Bar's initial" },
]
}
}
I'm using the ko.mapping plugin and my create handler for objects instantiates Obj from objects.foo and then objects.bar, returning the resulting two items in an array. This part works fine; I use
var view = {};
ko.mapping.fromJS(viewModel, mapping, view);
My issue is updating based on new data. (i.e., getting data from the server). I have an object of new data and I attempt
ko.mapping.fromJS(new_model, mapping, view);
I suspect this is incorrect but I have not been able to get it working despite extensive searching. (Trust me, it's been days. ): Anyway, thanks for any help.
EDIT: So I've mostly figured it out - I was depending too heavily on mapping.fromJS and certain things were not being wrapped into observables. I also realized that I didn't need the create(), only the update(), as it is called after create() anyway. If you have a similar problem let me know!
John,
When updating your data using ko.mapping be sure you don't create a new item. Your UI is already bound to the existing items, so you just want to update the values of the existing item properties; not create new ones. For the example you posted, you'll want to adjust your "update" method of your map to insert the new values into the correct ko.observable property, rather than creating a new object in it's place. The ko.mapping "update" method has a few different parameter lists depending on usage, with the third parameter being the target object of the map. You would want to update that object's properties.
obj.target[label].items[0].text(obj.data[label][0].text);
But, that's a bit of a mess. You'll probably want to create a second level of mappings (create / update) to handle "deep" object hierarchies like in your fiddle. For example one map for objects at the "foo/bar" level, and another call to ko.fromJS from within "update" with another map for the child Obj() objects.
After fixing that, you'll run into a couple simple binding errors that you can fix using another "with" binding, or a "foreach" binding for the child arrays.
Overall, you've just run into a couple common pitfalls, but nothing too severe. You can learn a bit more about a few of these pitfalls on my blog here : http://ryanrahlf.com/getting-started-with-knockout-js-3-things-to-know-on-day-one/
I hope this helps!

How does map work with a Backbone collection?

Goal: I am trying to create a case insensitive search that goes through my collection and tries to match the user query against model's name attribute. Right now if I want to find a specific model, the search query must be exact.
It seems there is no easy way to do something so simple in Backbone, not out of the box. The function map came to mind. What if I could go through the entire collection and change model's name attribute to lower case, then change user query to lower case as well and voila!
But the problem is I have no idea how to use Backbone Collection and map function. There is no documentation on map in Backbone docs, other than a link that leads you to underscore documentation with a super primitive example code using an array of three numbers.
This does not work...why?
this.collection.map(function(model) {
return model.get('name').toLowerCase();
});
Actually, all of underscore's collection methods are proxied on Backbone.Collection objects. when you do a collection.map(... it returns an array of objects returned by the mapped function. The solution presented by raina77ow does not work since a Backbone.Collection is not an array and assigning the result of the map to this.collection will destroy the collection itself.
If you want to filter a collection, I would recommend using the filter method. ( I assume you are working from a Backbone.View:
var filter = this.$('#search-field').val(),
filteredModels = this.collection.filter( function( model ) {
return model.get('name').toLowerCase() === filter;
};
this.collection.reset( filteredModels );
Note that any of underscore's proxied methods on collections will return an array of models. If you then want to use them, you can reset the collection with these models or, equivalently, set the collection's models attribute to the filtered results: this.collection.models = filteredModels. The first form has the advantage of triggering a reset event on the collection to which you can listen to and, for example re-render your view.

Partial mapping to existing object with Knockout JS

I have got a complex model which is contains a load of ko.observable, ko.observableArray and nested objects which contain even more of these observables.
Now originally I had to make methods within each of the models which in composition make up the larger model to take Json data and then populate its observables. Now I tried the ko.mapping plugin but when I use that doing:
ko.mapping.fromJS(jsonData, {}, existingModel);
Which appears to work for most objects, however I have noticed that when I do this it seems to completely overwrite the object, and as I am using knockout js validation i.e:
this.Name = ko.observable().extend({ required: true });
this.Age = ko.observable().extend({ required: true, digits: true });
Problem is that these validation attributes seem to be removed when using the mapping module, so is there a way to get the mapping plugin to just update the values, rather than tampering with the object schema...
I am more than happy to use a different mechanism other than ko.mapping if there is a better way to apply Json data to the models.
From http://knockoutjs.com/documentation/plugins-mapping.html (section Advanced usage)
Sometimes it may be necessary to have more control over how the mapping is performed. This is accomplished using mapping options. They can be specified during the ko.mapping.fromJS call. In subsequent calls you don’t need to specify them again.
So, for example, you can try something like this:
var self = this;
var mapping = {
update: function(arg) {
var data = arg.data;
return {
Name: data.Name && self.Name(data.Name),
Age: data.Age && self.Age(data.Age)
}
}
};
ko.mapping.fromJS(data, mapping);
I ended up having to stick with my approach although I did manage to reduce a LARGE amount of the code written to populate the existing fields by writing the simple plugin below:
https://github.com/grofit/knockout.mapping.merge
It is very simple and doesn't really do much other than just match up objects with the same name to their existing fields. I was hoping to manage child object creation, so it could populate the entire object tree, but alas I ran out of time.
Hopefully it would at least show a possible solution without having to write lots of verbose code to update a model.
If your needs are modest, you can do this with a simple vanilla JS for loop. This example assumes that you have an existing model called 'myViewModel', and data for a partial refresh called 'jsonData':
for (var prop in jsonData) {
if (myViewModel.hasOwnProperty(prop)) {
myViewModel[prop](jsonData[prop]);
}
}
As it's only updating the value, any additional attributes you've attached to the observables should remain in place.

Categories

Resources