-
19 Aug 2011 7:19 AM #1
Answered: Damn scoping, what am I missing??
Answered: Damn scoping, what am I missing??
Hi guys,
I'm testing some things and I thought that I fully understand scoping but I have a issue:
See the following code:
the problem isCode:Ext.define("MyCompany.MyScheduler", { extend : 'Sch.panel.SchedulerGrid', tbar : [ { xtype : 'buttongroup', columns : 3, title : Your menu, items : [ { iconCls : 'icon-prev', handler : function() { this.shiftPrevious(); } }, { text : 'Date', menu : Ext.create('Ext.menu.DatePicker', { handler : function(datePicker, pickedDate) { var startDateTime = new Date(pickedDate); startDateTime.clearTime(); startDateTime.setHours(5); var endDateTime = startDateTime.clone(); endDateTime.setHours(21); return schPanel.switchViewPreset('pnViewPreset', startDateTime, endDateTime); } }) }, { iconCls : 'icon-next', handler : function() { this.shiftNext(); } } ] } ], initComponent : function() { Ext.apply(this, { // Setup your static columns columns : [ { header : 'Header1', sortable: true, width: 150, dataIndex : 'Header1' }, { header : 'Header2', sortable: true, width: 100, dataIndex : 'Header2 } ] }); this.callParent(arguments); } });In both cases it is telling:this.shiftNext() AND this.shiftPrevious()
If I place the entire tbar code in:Uncaught TypeError: Object [object Object] has no method 'shiftNext'
Then it is working, but this is a workaround, the real bug is me, i still do not understand it in this context...Code:Ext.apply(this, { // Setup your static columns columns : [ { header : 'Header1', sortable: true, width: 150, dataIndex : 'Header1' }, { header : 'Header2', sortable: true, width: 100, dataIndex : 'Header2 } ] }); this.callParent(arguments);
This class is called from another JavaScript file like this:
Code:var scheduler = Ext.create("MyCompany.MyScheduler", { dndValidatorFn : this.validatorFn, viewConfig : {stripeRows : false, forceFit: true} })
Last edited by aacoro; 19 Aug 2011 at 9:53 AM. Reason: Typo
-
Best Answer Posted by mankz
Scope is tricky, until you get it

You have to put scope specific code in a template method (constructor, initComponent, onRender, etc) where you can get access to the component instance.
All you need to think about to figure out the scope is: What is 'this' when the relevant function is parsed.
In code above, as the class definition is parsed, the code is running in the global context - hence 'this' will point to the window object. But when you create an instance of a class, inside its constructor and any following method calls, 'this' will point to the instance.Code:alert('Right now, "this" is ' + this); Ext.define("MyCompany.MyScheduler", { extend : 'Sch.panel.SchedulerGrid', tbar : [ { xtype : 'buttongroup', columns : 3, title : Your menu, items : [ { iconCls : 'icon-prev', handler : function() { this.shiftPrevious(); } }, { text : 'Date', menu : Ext.create('Ext.menu.DatePicker', { handler : function(datePicker, pickedDate) { var startDateTime = new Date(pickedDate); startDateTime.clearTime(); startDateTime.setHours(5); var endDateTime = startDateTime.clone(); endDateTime.setHours(21); return schPanel.switchViewPreset('pnViewPreset', startDateTime, endDateTime); } }) }, { iconCls : 'icon-next', handler : function() { this.shiftNext(); } } ] } ], initComponent : function() { alert('Right now, "this" is ' + this); Ext.apply(this, { // Setup your static columns columns : [ { header : 'Header1', sortable: true, width: 150, dataIndex : 'Header1' }, { header : 'Header2', sortable: true, width: 100, dataIndex : 'Header2 } ] }); this.callParent(arguments); } });
-
19 Aug 2011 7:51 AM #2
I don't see a definition for shiftNext or shiftPrevious in your examples, so I can't tell where the scope mismatch lies.
Usually, though, the scope of a button in a toolbar will be the button, though, so you might have to walk the ownerCt chain or use up('xtype of your panel') to get to a containing panel. Try "alert(Ext.ClassManager.getDisplayName(this));" in your handler to confirm.
stevil
-
19 Aug 2011 9:51 AM #3
The definition is from Bryntum: http://bryntum.com/docs/#/api/Sch.panel.SchedulerGrid-method-shiftNext
hmm but alerting is giving me the following error:
If I console.log(this) i get the following result:Uncaught TypeError: Object #<Object> has no method 'getDisplayName'
Why is the DOMWindow the scope?Code:DOMWindow
Last edited by aacoro; 19 Aug 2011 at 10:08 AM. Reason: added console.log output
-
20 Aug 2011 3:45 AM #4Sencha - Community Support Team
- Join Date
- Nov 2007
- Location
- Helsingborg, Sweden
- Posts
- 2,489
- Vote Rating
- 56
- Answers
- 30
Scope is tricky, until you get it

You have to put scope specific code in a template method (constructor, initComponent, onRender, etc) where you can get access to the component instance.
All you need to think about to figure out the scope is: What is 'this' when the relevant function is parsed.
In code above, as the class definition is parsed, the code is running in the global context - hence 'this' will point to the window object. But when you create an instance of a class, inside its constructor and any following method calls, 'this' will point to the instance.Code:alert('Right now, "this" is ' + this); Ext.define("MyCompany.MyScheduler", { extend : 'Sch.panel.SchedulerGrid', tbar : [ { xtype : 'buttongroup', columns : 3, title : Your menu, items : [ { iconCls : 'icon-prev', handler : function() { this.shiftPrevious(); } }, { text : 'Date', menu : Ext.create('Ext.menu.DatePicker', { handler : function(datePicker, pickedDate) { var startDateTime = new Date(pickedDate); startDateTime.clearTime(); startDateTime.setHours(5); var endDateTime = startDateTime.clone(); endDateTime.setHours(21); return schPanel.switchViewPreset('pnViewPreset', startDateTime, endDateTime); } }) }, { iconCls : 'icon-next', handler : function() { this.shiftNext(); } } ] } ], initComponent : function() { alert('Right now, "this" is ' + this); Ext.apply(this, { // Setup your static columns columns : [ { header : 'Header1', sortable: true, width: 150, dataIndex : 'Header1' }, { header : 'Header2', sortable: true, width: 100, dataIndex : 'Header2 } ] }); this.callParent(arguments); } });
-
20 Aug 2011 3:46 AM #5Sencha - Community Support Team
- Join Date
- Nov 2007
- Location
- Helsingborg, Sweden
- Posts
- 2,489
- Vote Rating
- 56
- Answers
- 30
You'll also need to add this to maintain the scope pointing to the component instance:
Code:{ iconCls : 'icon-prev', scope : this, handler : function() { this.shiftPrevious(); } },
-
20 Aug 2011 11:59 AM #6
Yeah, thanks, this was my missing link. My code was refering to this in the global context...
I can work this one out now


Reply With Quote