I'm wondering is there a possibility to make this.model.save(data, options) in Backbone without writing data to model?
I have a server endpoint where I need to POST json { field1: 'bbb', field2: 'aaa' } - server writes these fields into db like list: [{ field1: 'bbb', field2: 'aaa' }].
The problem is that Backbone adds these fields to model as well. And I have model like { id: '111', field1: 'bbb', field2: 'aaa', list: [{ field1: 'bbb', field2: 'aaa' }] } and that's wrong..
Is there a way to make save without writing send data to model? Or maybe simply use jquery $.post method and set model on success?
I think the easiest way to fix this would be to either change the data returned by the server, or override the parse method in your model and remove the extra attribute.
A second thought would be to give your moel a single attribute of list and set that with the data dict and have the server return the same. This won't be 100% compatible with general Backbone model usage though.
gotta go..
You can define sync function and make ajax there
You can define parse function and write something like this
parse:function(data)
{
return data.list;
}
2 is the better approach. If setting some field will affect another one, server will return it and you will always have actual data in the model.
Related
If there's an optional field in the server returned JSON top structure. Backbone Model seem to cache previously set value. Lets say i get a JSON like this
{
label: "test_label",
attr1: "test1",
attr2: "test2"
}
when I say #model.get("label") i get "test_label". So later on, if i get a JSON like this
{
attr1: "test1",
attr2: "test2"
}
i get "test_label" when i query for #model.get("label"). Is this a known issue in backbone.js? I do something like this to fetch
#modelXhr = #model.fetch
success: (-> this.trigger('reset')).bind #model
I'm a beginner in javascript/coffeescript, What can i do so when i query for a field which doesn't exist in the latest returned model I won't get an older value? Appreciate your help
You should either clear the model beforehand using #model.clear() or (in my opinion the better way) ensure that the data format for a specific model type does not change. Return { label: null, ... }
You are then later on able to check for the existence of the label using #model.get("label")?
If you are not able to ensure data integrity throughout your requests, clear the model.
I have a simple REST application built in Sails and I want to save the correct data in a model attribute of type array.
Route to post
http://localhost:1337/locations/create?name=savassibeer&locations={latitude:23789472398.2344,longitude:2734637892.56756756}&locations={latitude:22.2344,longitude:2562.56756756,date:2014-02-15T11:00:00}
The result
{
name: "savassibeer",
locations: [
"{latitude:23789472398.2344,longitude:2734637892.56756756}",
"{latitude:22.2344,longitude:2562.56756756,date:2014-02-15T21:49:23.084Z}"
],
createdAt: "2014-02-15T21:49:23.084Z",
updatedAt: "2014-02-15T21:49:23.084Z",
id: "52ffe0e345d19ec72b4fac77"
}
How can I transform the strings in locations to a valid JSON Object and save it?
You're not going to be able to do this using URL shortcuts (i.e. hitting /locations/create in the browser). They're not designed to do type-guessing. If you want to save data this way, the answer is to write a custom create action in your Locations controller that will 1) validate the locations data as #marionebl mentions above, and 2) set the locations attribute as a Javascript array.
Let's say I have a resource with several fields, and some of them are read-only. Or maybe they belong in different use cases that I would like to handle differently on the server.
For instance, my bing resource looks like this:
{id: 1,
foo: "A",
bar: "B",
createdAt: "2013-05-05"}
I would like to get Restangular to PUT only some fields, executing requests like:
PUT /bing/1 {foo: "A"}
PUT /bing/1 {bar: "B"}
PUT /bing/1 {foo: "A", bar: "B"}
What I do not want to do is:
PUT /bing/1 {id: 1, foo: "A", bar: "B", createdAt: "2013-05-05"}
How can I achieve it?
I'm the creator of Restangular.
#Nicholas is absolutely right :). That's a PATCH and not a PUT. And Restangular does support it :).
elem.patch({foo: 2}) would be the way to go if elem is already a restangularized object.
Hope this helps!!
That's a PATCH not a PUT.
See https://www.rfc-editor.org/rfc/rfc5789
One way to do this is to pass the entire object to the patch method, including all the fields that you don't want to send to the backend, and then use a request interceptor to delete any unwanted fields before the request is sent.
For example, to always delete the field createdAt from any patch request you could do something like
app.config(function(RestangularProvider) {
RestangularProvider.setRequestInterceptor(function(element, operation, route, url) {
if (operation === 'patch') {
delete element.createdAt;
return element;
}
});
});
To learn more about request interceptors see the documentation on setRequestInterceptor
I haven't had a question from quite a while, but I finally ended up hitting a wall here. Anyways, to make this easy. I am trying to create a JSON store in extjs 3.4 (work related, and no I am not updating).
Well, I created the queries as usual with the proper response and fill it up. My problem is that I have 1 extra property on the JSON that I want to be able to pull and use on the app.
Sample of my JSON from the response object in chrome:
myInventory: [{Priority:1, PMNumber:444, Description:fix-a-tape, Assets:3, Storage_Count:0,…},…]
percent: 97.040498442368
totalCount: "3"
Now, I know this is correctly formatted because the Grid I am using gets populated, but I can't get the percent property. So my question is, how do you pull an extra parameter on the datastore building block of code when you have one extra parameter that is not usual on EXTjs, in my case the percent?
I tried doing a metachange on the JSONReader, but all I get is percent:"percent" on the properties as I inspect the datastore after it's creation.
Ext.data.JsonReader has a property jsonData which is exactly what you need. A quick example:
Ext.onReady(function() {
var store = new Ext.data.JsonStore({
url: 'data/test.json',
root: 'dataRoot',
fields: ['fieldA', 'fieldB'],
idProperty: 'id',
storeId: 'myStore'
});
store.on('load', function(store) {
console.log(store.reader.jsonData.someOtherProperty);
});
store.load();
});
and the data/test.json looks like this:
{
dataRoot: [{
id: 0,
fieldA: 'a',
fieldB: 'b'
}],
someOtherProperty: 'abc'
}
There could also be an alternative approach that you manually (not via store.load()) perform Ext.Ajax request, use the properties you need and then manually call Ext.data.JsonStore.loadData() using the data you got from Ajax request.
At this time my code fetches each collection separately but given that the same requests are made together I would like it to load the collections in one request.
This is what my request response would look like if I were to merge all:
[{id: 5, milestoneName: 'some milestone', tasks: [{id: 1, taskName: 'first task', dueDate: 'Jan 15'}, {id: 2, taskName: 'second task', dueDate: ''}]},{id: 6, milestoneName: 'some other milestone', tasks: [{id: 3, taskName: 'third task', dueDate: 'Jan 16'}, {id: 4, taskName: 'fourth task', dueDate: ''}]}]
Basically, there are milestones that contain tasks. At this point the milestone collection fetches the milestones and when they are fetched, the task collection(of each milestone) is initialized and fetches the tasks. This can take quite a while (2-3 seconds, that are obvious). If I could load them in one request everything would work faster.
milestoneModel = Backbone.Model.extend({});
milestoneCollection = Backbone.Collection.extend({
url: 'http://some-url',
model: milestoneModel
});
taskModel = Backbone.Model.extend();
taskCollection = Backbone.Collection.extend({
url: 'http://task-url',
model: taskModel
});
I would like the taskCollection to be part of the each milestoneModel and to be reset as soon as this request response arrives.
Ah. Nested models and fetching it all. :-) Basically, have your server send exactly what you're sending. Your JSON structure of the nested tasks collections are fine as is. Here is what you do.
In your Milestone Model, you modify the parse to look for the property tasks then you process it accordingly. For example:
parse: function(response) {
if (_.has(response, 'tasks')) {
if (this.tasks) { // Check if this model has a tasks collection already defined
this.tasks.reset(response.tasks); // It does, so reset it with data
} else {
this.tasks = new taskCollection(response.tasks); // It doesn't, so create one
}
delete response.tasks;
// Don't forget to delete tasks from response or it will be passed onto the model
// set and appear in your attributes
}
return response; // Do pass on all the other attributes that belong to the model
}
This assumes you want the taskCollection as a property of your Milestone model and not an attribute. It basically checks if a tasks array is present as a property of the response, if there is one, we check the model object if it has the tasks collection already defined. If it does, reset the collection with the data. If not, create the collection with data.
One more thing. I'm not sure if you have to do this or not. But I think when you fetch() your Milestones collection, you might have to pass an option parse:true. I kind of forget when you need to do this, or if this a relic from a previous Backbone. Try placing a console.log() in your parse to check if your Milestone model is properly parsing the response. If it isn't, then try passing the parse:true option.