how to set nested object properties in Backbone.Collection.get()? - backbone.js

I have an object with another nested object which I would like to modify using Backbone's .get() functionality. According to the docs, I can set the root level object keys, but is there a way to alter the nested properties as well?

You can set/get nested values but it will act as a replace not an update.
model = {'foo': {'bar': 'baz', 'qux': 'foo'}};
model.get('foo'); // {'bar': 'baz', 'qux': 'foo'}
model.set('foo', {'baz': 'qux'});
model.get('foo'); // {'baz': 'qux'}

Related

Updating Array of Objects in Firebase Realtime Database in React js

I have a problem with updating certain properties of an array of objects in a real-time database in Firebase.
My object looks like the following (see picture).
Now I want to update the IsComing property of the second participant object.
At the moment I use the updateIsComming() function, but this is not very convincing, because I have to rewrite the whole object.
function updateIsComming() {
const db = getDatabase();
update(ref(db, " your_path/EventModel/" + modelkey ), {
Location: "London",
Participants: [
{ Name: "Bella2", IsComming: "true" },
{ Name: "Tom", IsComing: "true" },
],
});
Instead, I just want to reference the specific prop from that array. For example
Participant[1].IsComming = false;
Is there any way I can access a specific array of an object directly.
Arrays as a data structure are not recommended in Firebase Realtime Database. To learn why, I recommend reading Best Practices: Arrays in Firebase.
One of the reasons for this is that you need to read the array to determine the index of the item to update. The pattern is:
Read the array from the database.
Update the necessary item(s) in the array in your application code.
Write the updated array back to the database.
As you already discovered, this is not ideal. As is common on NoSQL databases, consider an alternative data structure that better suits the use-case.
In this case, an alternative data structure to consider is:
Participants: {
"Bella2": true,
"Tom": true
}
In there, we use the name of the participant as the key which means:
Each participant can be present in the object only once, because keys in an object are by definition unique.
You can now update a user's status by their name with: update(db, "your_path/EventModel/" + modelkey + "/Participants/Tom", false).

Backbone Collection get property

Got a server returning a JSON object like so:
{
'key1':'value'
'key2':{
'key2_0':'value'
}
}
And a collection:
var Collection = Backbone.Collection.extend({
url:api.url//which returns the object above
});
var collection = new Collection();
collection.fetch({
success:function(data){
//do something
}
});
Now i need to use certain properties of the collection throughout my application, but say i need key1, i always have to do collection.at(0).get('key1');//returns 'value', because the data returned is stored within the collection, in a new Array at key 0.
Question:
How to directly... collection.get('key1')//now returns undefined... because it is.
I know i could expose an object to the global scope in the collection success function some_other_var = data.toJSON()[0] and access the some_other_var properties directly, but that's not what i'm looking for;
In order to use the get() function from a Backbone.Collection you need to know the model id or cid wanted.
For instance, lets say your data coming from the server is like follow:
[{
id: '123',
name: 'Alex'
}, {
id: '456',
name: 'Jhon'
}]
In that case you can do this:
this.collection.get('123').get('name') // Return "Alex"
Keep in mind that collection is just a set of model, so behind the scenes by doing collection.get() you are getting a model
Tip: If you don't have any kind of id in your server data, there is always the option of using underscore methods:
find
filter
some
contains
etc
It seems like you're trying to ascribe attributes to a collection, but a collection is merely a set of models. Having additional data that is constant throughout the collection suggests that it should be wrapped inside another Model, which is demonstrated here: Persisting & loading metadata in a backbone.js collection

Backbone.js model: attribute of type array maintains data between instances

Suppose I have following Backbone.js model:
class App.Models.Article extends Backbone.Model
defaluts:
id: ''
name: ''
tags: []
and a view to display its contents. In a master view I create an instance of article view by passing a newly created Article as :
v = new App.Views.ArticleView({ model: new App.Models.Article() })
and render it to the page.
In the article view and by user interaction some tags are added to the tags array by following code:
addTag: ->
tags = #model.get('tags')
tags.push({id: '', name: 'foo'})
tags.push({id: '', name: 'bar'})
So far so good! Then I close the article view and render another view. Later I want to again render the article view so the code:
v = new App.Views.ArticleView({ model: new App.Models.Article() })
runs again.
The problem is after rendering, I still can see previously entered tags in the tags array i.e. if inside articles view, I write:
console.log(#model.get('tags'))
it will output two objects added before. I expect that each instance has its default values when created not something that there is no more reference to it. Any ideas? Any issues with Coffescript?
P.S. I hope the problem statement is clear enough :)
Don't use arrays and objects in defaults, they will get shared across model instances. If you want tags to be empty array, add that in initialize function.
var MyModel = Backbone.Model.extend({
initialize:function(){
this.set('tags', [])
}
})
Solved!
The problem is that Coffeescript attaches default to the prototype, so defining the defaults as follows solves the problem:
defaults: ->
id: ''
name: ''
tags: []
Again it is attached to the prototype but as a function, it returns an empty object for each call.

How to set multiple values at one time to Ext.data.Model?

In Ext.data.Model class we have set(fieldName, newValue) method which sets one model field to the given value.
How to set multiple values at one time? Something like:
Ext.data.Model.set({
field1: 'value1',
field2: 345,
field3: true
});
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Model
You can set the field to set, or an object containing key/value pairs
record.set({
field1: value,
field2: value2
});
// or
record.set(field1, value);
record.set(field2, value2);
That's not possible, but as per my understanding you only want to merge this different calls for setting a value in model when you need to notify about changes in model only once to store so store will only fire update event once
If this is the case for you then you can use beginEdit and endEdit functions
var model = new Ext.data.Model();
model.beginEdit();
model.set('field1', 'value1');
model.set('field2', 345);
model.set('field3', true);
model.endEdit();
Just create a new record which returns a blank record with all the model fields
//this one is for the grid model
var blank_record = Ext.create(grid.store.model);
Create an object to set the new values to fields
var new_record = {
'field1':'value1',
'field2':'value2',
'field3':'value3'
};
then set the object values to the blank record
blank_record.set(new_record);
Further if u want to add the newly created record to the grid
grid.store.add(blank_record);
Hope this helps
I'm late to the party but here's another way to do it:
var rec = new Ext.data.Model({
field1: 'value1',
field2: 'value2',
field3: 'value3'
});
Can't you do this with just Ext.create() ?
As explained here:
http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.ModelManager-method-create

Dynamic Model with ExtJS 4

With ExtJS 3.x, I was able to use the "fields" property of a Store, but it seems with ExtJS 4 I have to absolutely use a Model. It's fine, but in my case, it's not a static Model, and I need to define the fields on the fly and sometimes to change them.
I could re-create a Model, but I need to use a different name as it's apparently not possible to modify an exisiting Model, neither delete it. If I try to use Ext.regModel with the same name, ExtJS crashes.
Thanks for your help!
4.1 UPDATE:
As an update... in 4.1 there is now a static method setFields which can be used to define the model prototype fields. It works well in a controller's init method.
When I did this, I wanted to have some static fields defined in the model class and then set some more dynamically. Unfortunately the new setFields method replaces all fields with the argument, it was easy enough to handle though.
This example uses the MVC pattern where my model and store are included in the controller's model array and store array (providing me with the handy getters used below):
Ext.define('ST.controller.Main', {
extend: 'Ext.app.Controller',
models: ['User', 'Reference'],
stores: ['CurrentUser', 'PermissionRef'],
views: ['MainPanel'],
init: function() {
var me = this;
me.getPermissionRefStore().on('load', function(store, records) {
var model = me.getUserModel();
// this returns the static fields already defined
// in my User model class
fields = model.prototype.fields.getRange();
// add the permission options (dynamic fields) to the static fields
Ext.each(records, function(permission) {
fields.push({name: permission.get('name'), type: 'bool'});
});
// 4.1 method to update the User model fields
model.setFields(fields);
// now load the current user (it will use the updated model)
me.getCurrentUserStore().load();
});
}
});
The User model and CurrentUser store are created exactly like regular, non-dynamic models and stores would be and included in their respective controller arrays, the 'User' model is simply missing the dynamic fields which are added as shown above.
I also went into that problem. I have a service which is responsible for fetching metadata from the server and adapting the models and stores to this metadata.
I therefore defined an empty model and configured the store to use this model.
When the meta data is processed, I add the new/additional fields to the prototype of the model like this (metaDataStore is the store containing the meta data, model is the model which can be obtained from the model manager):
var fields = [];
metaDataStore.each(function(item) {
fields.push(Ext.create('Ext.data.Field', {
name: item.get('field')
}));
});
model.prototype.fields.removeAll();
model.prototype.fields.addAll(fields);
When I then call load on a store using this model or create new model instances the new fields are processed correctly.
Here's a very simple example. Just use a normal Ext.data.Store but instead of a model, specify the fields property:
// you can specify a simple string ('totally')
// or an object with an Ext.data.Field ('dynamic')
var fields = ['totally', {name : 'dynamic', type : 'string'}];
var newStore = new MyApp.store.Object({
fields : fields
// other options like proxy, autoLoad...
});
Don't specify a model property - it seems that it would override the fields property.
I also wanted to change the columns and content of an existing grid dynamically:
// reconfigure the grid to use the new store and other columns
var newColumns = [
{header: 'Totally', dataIndex: 'totally'},
{header: 'Dynamic', dataIndex: 'dynamic'}
];
myGrid.reconfigure(newStore, newColumns);
From the Ext JS 4 documentation about the "fields" property of Ext.data.Store:
This may be used in place of
specifying a model configuration. The
fields should be a set of
Ext.data.Field configuration objects.
The store will automatically create a
Ext.data.Model with these fields. In
general this configuration option
should be avoided, it exists for the
purposes of backwards compatibility.
For anything more complicated, such as
specifying a particular id property or
assocations, a Ext.data.Model should
be defined and specified for the model
config.
So be careful - Sencha may remove it in the future.

Resources