backbonejs's get method doesn't work - backbone.js

suppose I have a model:
window.PageModel = Backbone.Model.extend({
default:{
"device":"ipad",
"lang":"zh-Hans",
"page":2,
"uuid":"3c30e128-ed44-43a7-960a-e937457b8b58"
},
initialize: function () {
console.log('lang',this.get('lang'));
console.log('device',this.get('device'));
}
})
but when I initialize it,
window.pageModel = new PageModel();
the firebug tell me "lang" and "device" is undefined.
Why this happened? How can I solve this problem ?

you should be using defaults:{} instead of default:{}
so your code will be
defaults:{
"device":"ipad",
"lang":"zh-Hans",
"page":2,
"uuid":"3c30e128-ed44-43a7-960a-e937457b8b58"
}

Related

Access static members in mixins

The instruction this.constructor doesn't work in mixins. I get an undefined value. I wonder why it happens and is it possible to use this instruction. There is a code example:
qx.Mixin.define("MZoomable", {
statics: {
MAX_ZOOM: 500
},
members: {
printMaxZoom: function(){
alert(this.constructor.MAX_ZOOM);
}
}
});
qx.Class.define("MyClass", {
extend: qx.core.Object,
include: [MZoomable],
constuct: function(){
this.base(arguments);
}
});
const o = new MyClass();
o.printMaxZoom();
alert in printMaxZoom will show undefined word.
The answer is that this.constructor refers to the class of the object at runtime, and that would be MyClass. I would expect that if you modified printMaxZoom to be:
printMaxZoom: function(){
alert(this.constructor === MyClass);
}
Then you would get an alert that says "true".
This is an inherent characteristic an environment where the type is determined (including the addition of a mixin) at runtime.
If you want to refer to static members of a Mixin, you should use the absolute syntax, eg:
printMaxZoom: function(){
alert(MZoomable.MAX_ZOOM);
}
Note that it is always good practice to use the absolute path for static variables, and it is often a bug to use this.constructor as a shortcut.
For example:
qx.Class.define("MyClassOne", {
extend: qx.core.Object,
construct: function(){
this.base(arguments);
alert(this.constructor.MY_VALUE);
},
statics: {
MY_VALUE: 23
}
});
qx.Class.define("MyClassTwo", {
extend: MyClassOne
});
// creates an alert that says "23"
var one = new MyClassOne();
// creates an alert that says "undefined"
var one = new MyClassTwo();
The issue is the same as the one in your question, in that this.constructor is the actual class of the object, and not the class (or mixin) where the this.constructor statement appears.

why behaviors are not allowed to pass dynamically?

I am working on Marionette.behavior.I was trying to pass the behaviors hash dynamically at the time of view initialization but it is not getting assigned to the behaviors object of view.because behaviors are getting initialized at the time of view construction.
so we achieved the solution in the following way but is it the right way to achieve it?
is there any other way to achieve? and
why behaviors are not allowed to pass dynamically?
Here's the code:
var Behaviour = new Marionette.Application();
Behaviour.addRegions({
mainRegion:"#main-region"
});
var Person = Backbone.Model.extend({
defaults:{
firstName:"NA",
lastName:"NA",
phoneNumber:"NA",
presentAddr:"NA",
permanantAddr:"NA"
}
});
var buttonView=Marionette.ItemView.extend({
template:"#buttontemplate",
constructor:function(options){
this.behaviors = options.behaviors;
Marionette.ItemView.apply(this, arguments);
},
events:{
"click .display":"displayDetail"
},
displayDetail:function(){
this.triggerMethod("DisplayPersonDetails");
},
//behaviors:{Behavior1:{ },Behavior2:{ }}
})
var PersonDetailsView = Marionette.ItemView.extend({
template:"#static-template",
ui: {
"Change": ".change"
},
events:{
"click #ui.Change":"changeBehavior"
},
changeBehavior:function(){
},
});
var Behavior1 = Marionette.Behavior.extend({
onDisplayPersonDetails:function(){
var person=new Person({firstName:"abhijeet",lastName:"avhad",phoneNumber:"9604074690",permanantAddr:"sangamner",presentAddr:""})
var myView = new PersonDetailsView({model:person});
Behaviour.mainRegion.show(myView);
}
});
var Behavior2 = Marionette.Behavior.extend({
onDisplayPersonDetails:function(){
var person =new Person({firstName:"abhijeet",lastName:"avhad",phoneNumber:"9604074690",permanantAddr:"",presentAddr:"shivajinagar"})
var myView =new PersonDetailsView({model:person});
Behaviour.mainRegion.show(myView);
}
});
Behaviour.on("initialize:after", function(){
console.log(" started!");
Marionette.Behaviors.behaviorsLookup = function() {
return window.Behaviors;
};
window.Behaviors = {};
window.Behaviors.Behavior1 = Behavior1;
window.Behaviors.Behavior2 = Behavior2;
var buttonview=new buttonView({behaviors:{Behavior1:{ },Behavior2:{}}});
Behaviour.mainRegion.show(buttonview);
});
Behaviour.start();
The other way of achieving that is in your definition declare a function that returns the behaviors supplied at initialization, like this:
var buttonView=Marionette.ItemView.extend({
...
behaviors: function () {
return this.options.behaviors;
},
...
This is because the Marionette applies the behaviors in the constructor:
if (_.isObject(this.behaviors)) {
new Marionette.Behaviors(this);
}
You may try to do the same in your initialize method, but I'm not sure if it will work correctly if you already had some behaviors assigned beforehand.
After hacking through the source, I've come up with the following. It breaks encapsulation, which leads me to believe that there is probably a better way. Nonetheless, until I find it, this is going straight into production.
// Define Behavior.
var Behavior1 = { /* Behavior definition */ }
// Create View like normal.
var view = new ItemView({
behaviors: {
behavior1: { behaviorClass: Behavior1 }
}
});
// Here's the ugly part.
view.undelegateEvents();
view._behaviors = Marionette.Behaviors(subview);
view.delegateEvents();
After you do that, your Behaviors should all work.
Behavior can be passed directly with behaviorClass property within declaration of behaviors:
As seen in the marionette.behaviors docs, for example we have Tooltip behavior, which we want to pass directly and not from global list.
define(['marionette', 'lib/tooltip'], function(Marionette, Tooltip) {
var View = Marionette.ItemView.extend({
behaviors: {
Tooltip: {
behaviorClass: Tooltip, // <-- passing the behavior directly here
message: "hello world"
}
}
});
});

Passing JSON object as parameter from View to Controller function?

Basically I've a panel called DummyPanel, Now on dummypanel initialize event I've called a controller function like as follows:
var me = component;
var fieldCollection =
{
"Order" : 'ordNumber',
"Ref": 'refNumber'
};
me.fireEvent('myControllerFunction','Param1', fieldCollection, 'Param3');
Now I want to get fieldCollection JSON object value within function myControllerFunction, to get value from fieldCollection I'm using following code:
myControllerFunction(param1, collection, param3)
{
Ext.Msg.alert(collection.Order);
}
But it does not return anything. So please let me know how to resolve this problem!!
Any comment will appreciated!!
I'm not quite sure what it means "But it does not return anything", but I'll try.
So, your "DummyPanel" view have a alias or itemId property. In yor controller (in init() function), you need "keep track" of your view. For example:
In your view:
me.fireEvent('myEventName','Param1', fieldCollection, 'Param3');
In your controller:
init:function(){
var me = this;
this.control({
'panel[itemId=your-view-itemId]': { // call your function after event
myEventName: me.myControllerFunction
}
});
...
},
...
myControllerFunction: function(...) {
...
}
Should it not be
Ext.Msg.alert(collection["Order"])?
Or if you want to keep Ext.Msg.alert the way it is fieldCollection should be defined this way
var fieldCollection =
{
Order : 'ordNumber',
Ref : 'refNumber'
};

How to pass collection inside jeditable function?

I want to edit my collection using jeditable, where modifyCollection is a function associated with the event dblclick. I have the following code:
initialize : function(options) {
view.__super__.initialize.apply(this, arguments);
this.collection = this.options.collection;
this.render();
},
render : function() {
var template = _.template(tpl, {
collectionForTemplate : this.collection ,
});
this.el.html(template);
return this;
},
modifyCollection : function (event){
$('#name').editable(function(value, settings) {
return (value);
}
,
{ onblur: function(value) {
this.modelID=event.target.nameID;
this.collection = this.options.collection;
console.log("This Collection is: " + this.collection); //Shows : undefined
//
this.reset(value);
$(this).html(value);
return (value);
}
});
The idee is to update the model and subsequently, the collection by means of jeditable. The in place editing works fine, but the problem is, I am not able to pass the collection into the function. I want to save all the changes to my collection locally and send them to the server at a later time. What am I doing wrong here?
Moved the comment to a formal answer in case other people find this thread.
The this inside your onblur() function is not pointing to this collection. Try adding var self = this; inside your modifyCollection() function then in your onblur() change this.collection to self.collection like so:
modifyCollection : function (event) {
var self = this; // Added this line
// When working with functions within functions, we need
// to be careful of what this actually points to.
$('#name').editable(function(value, settings) {
return (value);
}, {
onblur: function(value) {
// Since modelID and collection are part of the larger Backbone object,
// we refer to it through the self var we initialized.
self.modelID = event.target.nameID;
self.collection = self.options.collection;
// Self, declared outside of the function refers to the collection
console.log("This Collection is: " + self.collection);
self.reset(value);
// NOTICE: here we use this instead of self...
$(this).html(value); // this correctly refers to the jQuery element $('#name')
return (value);
}
});
});
UPDATE - Foreboding Note on self
#muistooshort makes a good mention that self is actually a property of window so if you don't declare the var self = this; in your code, you'll be referring to a window obj. Can be aggravating if you're not sure why self seems to exist but doesn't seem to work.
Common use of this kind of coding tends to favor using that or _this instead of self. You have been warned. ;-)

How to uncheck all tree nodes in Ext.tree.TreePanel?

I would like a 'reset' method to uncheck all the checked nodes in Ext.tree.TreePanel.
tree.getRootNode().cascade(function(n) {
var ui = n.getUI();
ui.toggleCheck(false);
});
As found here:
http://www.sencha.com/forum/showthread.php?12888-solved-programatically-unchecking-checked-tree-nodes&p=62845#post62845
I found a method as below, but seems the 'casecade' method do not worked well, I need call 'reset' several times to unchecked all the checked children:
reset: function (){
startNode = this.root;
var f = function () {
if (this.attributes.checked) {
this.attributes.checked = false;
this.getUI().toggleCheck(false);
}
};
startNode.cascade(f);
}
I was unable to get either of the other answers to work with Extjs 4.0.7. Also, the use of the "cascade" method issued a warning that it's deprecated. It recommended using "cascadeBy" instead. Other than the method name, I was unable to find a difference in the method signature (same arguments, this, behaviour).
However, I was able to find this code that worked:
{
xtype: 'button',
text: 'Deselect All',
listeners:{
click: function(){
var tree = Ext.ComponentQuery.query( 'treepanel[itemId=user_flags_tree]')[0];
tree.getRootNode().cascadeBy(function(){
this.set( 'checked', false );
});
}
}
}
Thanks to this post:
http://www.sencha.com/forum/showthread.php?149627-Programmaticaly-check-uncheck-checkboxes-in-the-Tree-panel
var nodes = treePanel.getView().getNodes();
var records = treePanel.getView().getRecords(nodes);
for (var i = 0; i < records.length; i++) {
records[i].set('checked',true);
}

Resources