PDA

View Full Version : Problem with refs in controller



b3f3
29 Sep 2013, 8:46 AM
Hello,

In a controller, I've declared refs to get a view instance but it doesn't work.
Here is my code :

Application :

Ext.application( {
name: 'APP',
controllers: [
...
'administration.Migration',
...
],
...
});

Controller :

Ext.define( 'APP.controller.administration.Migration', {
extend: 'Ext.app.Controller',

views: [
'body.administration.Migration',
'body.administration.migration.StartWindow'
],

refs: [{
selector: 'admin-migration',
ref: 'adminMigrationPanel'
}],

migrationStart: function() {
this.getBodyAdministrationMigrationStartWindowView().create().show();
},

execute: function(params) {
this.executeStep(0, params);
},

executeStep: function(step, params) {
var me = this;

Ext.Ajax.request({
url: 'migration/executeStep/' + step,
method: 'POST',
params: params,
success: function(response, opts) {
console.log(me.getAdminMigrationPanel());
},
failure: function(response, opts) {
console.log(response);
}
});
}
} );

View :

var startMenuItem = Ext.create('Ext.menu.Item', {
text: 'Démarrer la migration',
iconCls: 'gear-go',
handler : function(item) {
APP.controller.administration.Migration.prototype.migrationStart();
}
});

var eraseConsoleMenuItem = Ext.create('Ext.menu.Item', {
text: 'Effacer la zone du journal',
iconCls: 'erase',
handler : function(item) {
item.up('admin-migration').clear();
}
});

var tb = Ext.create('Ext.toolbar.Toolbar', {
items: [{
text: 'Action',
menu: {
items: [
startMenuItem,
'-',
eraseConsoleMenuItem
]
}
}]
});

Ext.define('APP.view.body.administration.Migration', {
extend: 'Ext.panel.Panel',
xtype: 'admin-migration',
tbar: tb,

clear: function() {
this.update();
}
});

but in controller me.getAdminMigrationPanel() doesn't work, it generate this error :

Uncaught TypeError: Object [object Object] has no method 'getAdminMigrationPanel'
Can you help me ?
Thanks

mehdiraza
29 Sep 2013, 11:09 AM
Try changing the selector to selector: '#admin-migration',

AND

Specify itemId:'admin-migration' in the config where you define the panel.

b3f3
29 Sep 2013, 11:26 AM
same error :

Uncaught TypeError: Object [object Object] has no method 'getAdminMigrationPanel'

mehdiraza
29 Sep 2013, 11:31 AM
I think there is another problem, trying changing your code as following:


Ext.Ajax.request({
url: 'migration/executeStep/' + step,
method: 'POST',
params: params,
success: function(response, opts) {
console.log(this.getAdminMigrationPanel());
},
failure: function(response, opts) {
console.log(response);
},
scope:me
});

b3f3
29 Sep 2013, 11:36 AM
I did it but problem persist

mehdiraza
29 Sep 2013, 11:39 AM
Try printing the "me" and "this" in console.log(me,this) before accessing the method and you will know what object is passed. You can get an idea form there.

b3f3
29 Sep 2013, 11:42 AM
Ok, me and this are the same

me :

Object {self: function, superclass: Object, config: objectClass, initConfigList: Array[0], initConfigMap: Object…}



$className: "APP.controller.administration.Migration"
$namespace: "APP"
HasListeners: function () {}
config: objectClass
configMap: Object
execute: function (params) {
executeStep: function (step, params) {
getBodyAdministrationMigrationStartWindowView: function () {
getBodyAdministrationMigrationView: function () {
initConfigList: Array[0]
initConfigMap: Object
migrationStart: function () {
refs: Array[1]
self: function constructor() {
superclass: Object
views: Array[2]
__proto__: Obje

this :

Object {self: function, superclass: Object, config: objectClass, initConfigList: Array[0], initConfigMap: Object…}



$className: "APP.controller.administration.Migration"
$namespace: "APP"
HasListeners: function () {}
config: objectClass
configMap: Object
execute: function (params) {
executeStep: function (step, params) {
getBodyAdministrationMigrationStartWindowView: function () {
getBodyAdministrationMigrationView: function () {
initConfigList: Array[0]
initConfigMap: Object
migrationStart: function () {
refs: Array[1]
self: function constructor() {
superclass: Object
views: Array[2]
__proto__: Object

b3f3
29 Sep 2013, 11:49 AM
...and refs exists :


refs: Array[1]

0: Object

ref: "adminMigrationPanel"
selector: "#admin-migration"
__proto__: Object


length: 1
__proto__: Array[0]

mehdiraza
29 Sep 2013, 12:01 PM
There is another point, you are right that ref exists, but I couldn't see anywhere if any instance is created for admin migration panel, its only defined. It should be added somewhere in some container and an instance will be created with the specified itemId.

This is what I understand, may be I am wrong.

b3f3
29 Sep 2013, 12:05 PM
an instance exists because this code works fine :

console.log(Ext.ComponentQuery.query('admin-migration')[0]);

ettavolt
30 Sep 2013, 4:12 AM
You need to do some tracing in Ext.app.Controller's code to understand, why accessor is not defined.
From what we see, definitions look correct.

b3f3
4 Oct 2013, 4:56 AM
You need to do some tracing in Ext.app.Controller's code to understand, why accessor is not defined.
From what we see, definitions look correct.
Ok, that's done :


Ext.define('Ext.app.Controller', {
...
ref: function(refs) {
var me = this,
i = 0,
length = refs.length,
info, ref, fn;

refs = Ext.Array.from(refs);

me.references = me.references || [];

for (; i < length; i++) {
info = refs;
ref = info.ref;
fn = 'get' + Ext.String.capitalize(ref);

if (!me[fn]) {
me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
}
me.references.push(ref.toLowerCase());
}
console.log(me);
},
...
getRef: function(ref, info, config) {
console.log('XXX');
...
hasRef: function(ref) {
console.log('YYY');
...
And result of 1st console.log give me :

[I]constructor {application: constructor, id: "administration.Migration", hasListeners: HasListeners,events: Object, references: Array[1]…}



_initialized: true
application: constructor
eventbus: constructor
events: Object
getAdminMigrationPanel: function () {

arguments: null
caller: null
length: 0
name: ""
prototype: Object
__proto__: function Empty() {}
<function scope>


hasListeners: HasListeners
id: "administration.Migration"
references: Array[1]

0: "adminmigrationpanel"
length: 1
__proto__: Array[0]


__proto__: Object



We can see that getAdminMigrationPanel is declared.
But when I call getAdminMigrationPanel(), 2nd and 3rd console.log does not return anythig !?
What's happen ?

b3f3
4 Oct 2013, 7:25 AM
And still :

Uncaught TypeError: Object [object Object] has no method 'getAdminMigrationPanel'
(ExtJs 4.2.0.663)

dawesi
4 Oct 2013, 8:38 PM
if you're using an application, theres no need to use procdural javascript to define your class. use configuration. it's easier to maintain as your app gets bigger. If you need to break functionality out, put it into another class, or a mixin.

also don't use hypens in your xtypes, it is bad practice and keep everything lowercase in xtype or other aliases

use a custom attribute called 'action' to give each button (or navigation tool) a name, you could use itemId, but action has become a defaco standard in this community for buttons.




Ext.define('APP.view.body.administration.Migration', {
extend: 'Ext.panel.Panel',
xtype: 'adminmigration',
tbar: [{
text: 'Action',
menu: {
items: [
{ text: 'Démarrer la migration',
iconCls: 'gear-go',
action : 'start' // then use ref "adminmigration [action=start]" to handle in controller
handler : function(item) {
APP.controller.administration.Migration.prototype.migrationStart;
}
},
'-',
{ text: 'Effacer la zone du journal',
iconCls: 'erase',
action : 'erase', // see not on above.
handler : function(item) {
item.up('admin-migration').clear();
}
}
]
}
}]

})

ettavolt
6 Oct 2013, 10:16 PM
Ok, me and this are the same

me :

Object {self: function, superclass: Object, config: objectClass, initConfigList: Array[0], initConfigMap: Object…}



$className: "APP.controller.administration.Migration"
$namespace: "APP"
HasListeners: function () {}
config: objectClass
configMap: Object
execute: function (params) {
executeStep: function (step, params) {
getBodyAdministrationMigrationStartWindowView: function () {
getBodyAdministrationMigrationView: function () {
initConfigList: Array[0]
initConfigMap: Object
migrationStart: function () {
refs: Array[1]
self: function constructor() {
superclass: Object
views: Array[2]
__proto__: Obje

this :

Object {self: function, superclass: Object, config: objectClass, initConfigList: Array[0], initConfigMap: Object…}



$className: "APP.controller.administration.Migration"
$namespace: "APP"
HasListeners: function () {}
config: objectClass
configMap: Object
execute: function (params) {
executeStep: function (step, params) {
getBodyAdministrationMigrationStartWindowView: function () {
getBodyAdministrationMigrationView: function () {
initConfigList: Array[0]
initConfigMap: Object
migrationStart: function () {
refs: Array[1]
self: function constructor() {
superclass: Object
views: Array[2]
__proto__: Object



Hm... After some gazing it started to look like a prototype, not an instance. How do you call executeStep?

b3f3
9 Oct 2013, 1:39 PM
Hm... After some gazing it started to look like a prototype, not an instance. How do you call executeStep?
In controller itself :

execute: function(params) {
Ext.ComponentQuery.query('adminmigration')[0].clearContent();
this.executeStep(0, params);
},


if you're using an application, theres no need to use procdural javascript to define your class. use configuration. it's easier to maintain as your app gets bigger. If you need to break functionality out, put it into another class, or a mixin.

also don't use hypens in your xtypes, it is bad practice and keep everything lowercase in xtype or other aliases


OK I understand, it's done.



use a custom attribute called 'action' to give each button (or navigation tool) a name, you could use itemId, but action has become a defaco standard in this community for buttons.




Ext.define('APP.view.body.administration.Migration', {
extend: 'Ext.panel.Panel',
xtype: 'adminmigration',
tbar: [{
text: 'Action',
menu: {
items: [
{ text: 'Démarrer la migration',
iconCls: 'gear-go',
action : 'start' // then use ref "adminmigration [action=start]" to handle in controller
handler : function(item) {
APP.controller.administration.Migration.prototype.migrationStart;
}
},
'-',
{ text: 'Effacer la zone du journal',
iconCls: 'erase',
action : 'erase', // see not on above.
handler : function(item) {
item.up('admin-migration').clear();
}
}
]
}
}]

})


I'm not really sure to understand this :
then use ref "adminmigration [action=start]" to handle in controller
Like this ? (in APP.controller.administration.Migration) :

Ext.ComponentQuery.query('adminmigration [action=start]').handler = function() {
...
If not, can you explain to me with an example ?
Thanks

ettavolt
10 Oct 2013, 1:48 AM
In controller itself :

execute: function(params) {
Ext.ComponentQuery.query('adminmigration')[0].clearContent();
this.executeStep(0, params);
},

I should get this from first post....
Anyway, how do you call execute()?
Like this?


handler : function(item) {
APP.controller.administration.Migration.prototype.migrationStart();
}

It would be nice if you could provide whole call stack.