PDA

View Full Version : How to init controller for a module of desktop?



phamtranquocviet
25 Feb 2012, 9:38 PM
Hi,
I got an admin console show up in my desktop, but I can't find a way to hook it to its corresponding controller. Code below tries to use "afterreader: initController()" to init controller but errors out this:

this.application is undefined
this.application.control(selectors, listeners, this);


Ext.define("Iip.view.iip.adm.AdminConsole", {
extend: "Ext.ux.desktop.Module",
controllers: ["iip.adm.AdminConsoles"],
...

init : function(){
this.launcher = {
handler : this.createWindow,
...
};
},

createWindow : function(){
...
win = desktop.getWindow("admin-console") || this.createNewWindow(desktop);
win.show();
return win;
},

initController: function(westPanel, opts) {
var controller = Ext.create("Iip.controller.iip.adm.AdminConsoles");
controller.init();
},

createNewWindow: function(desktop) {
return desktop.createWindow({
...
layout: "border",
items : [
{
region: "west",
....
layout: "accordion",
items: this.getMenu(),
afterrender: this.initController()
},
...
]
});
},

getMenu: function() {
...
return menu;// array of menu object from server
}
});

vietits
25 Feb 2012, 11:39 PM
initController: function(westPanel, opts) {
var controller = Ext.create("Iip.controller.iip.adm.AdminConsoles");
controller.init();
},

You should not create controller this way, try to use <application>.getController().


initController: function(westPanel, opts) {
var controller = <your application>.getController("Iip.controller.iip.adm.AdminConsoles");
controller.init();
},

Let have a look at the Ext.application.getController() to see why you have to do this.


...
getController: function(name) {
var controller = this.controllers.get(name);


if (!controller) {
controller = Ext.create(this.getModuleClassName(name, 'controller'), {
application: this,
id: name
});


this.controllers.add(controller);
}


return controller;
},
...

phamtranquocviet
26 Feb 2012, 9:16 PM
Thanks. That helped me get initController to call my controller, which, however, cannot find the menu item on in the accordion that sits in the left window. Thanks for any help. Here is my controller code:


Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
// All of the the following debugging (above this.control) show an empty array.
var el = Ext.ComponentQuery.query("Iip");
//var el = Ext.ComponentQuery.query("Iip panel[region=west] #acl");
//var el = Ext.ComponentQuery.query("Iip panel[region=west]");
console.log(el);
this.control({
"Iip panel[region=west] #acl": /*No matches, thus no log shows*/ {
click: function() {
console.log("clicked...");
}
}
});
}
});

vietits
26 Feb 2012, 11:14 PM
I don't think getting your controller in the way I suggested causes the problem of not finding the menu item. I think it should be other reasons. Right now I can't tell what it is because I don't know what your view looks like?

yAdEs
27 Feb 2012, 8:23 AM
I guess, just guess, you haven't creat your view, so you can't find it.
You need to create that module manually.

yAdEs
27 Feb 2012, 8:28 AM
And is that ComponentQuery right?
It should be "lip > panel[region=west] #cal" right?

phamtranquocviet
27 Feb 2012, 8:45 PM
Thanks vietits and yAdEs.

I think I should describe the linkage between the sencha desktop and my app before you can help me. Here it is: My "Start" menu has a menu called "Admin Console". When clicking it, a window shows up. Inside the window is a border layout. The left is an accordion which has one item called "Access Control Manager". The "center" pane is a tab panel. This much works. I can actually see the window with the border layout with "Access Control Manager" item inside the accordion on the left pane.

The following does not work:

- I want a tab to open a new tab in the "center" pane when "Access Control Manager" menu item in the accordion on the left is clicked. However, my controller is not able to find the "Access Control Manager" item. My previous codes showed that "Admin Console" is a module of the desktop (extending Ext.ux.desktop.Module)... For some reason, "Access Control Manager" menu item inside the accordion, which is inside the "Admin Console", which is inside a window, which is a module of the web desktop cannot be found.

This is just a personal project to learn extjs. So, I can zip the whole app and upload if you need it to help me. Thanks again for your help.

vietits
27 Feb 2012, 10:41 PM
@phamtranquocviet,

I don't think you should zip and upload all your project but only post the code of 'Admin console' window then everybody can help you.

phamtranquocviet
28 Feb 2012, 8:30 AM
Thanks vietits.

Here is my "Admin Console" view file:

Ext.define("Iip.view.iip.adm.AdminConsole", {
extend: "Ext.ux.desktop.Module",
controllers: ["Iip.controller.iip.adm.AdminConsoles"],
alias: "widget.admin-console",

// Props or configs
id: "admin-console",

// Create "Admin Console" menu item on start menu
init : function(){
// Define launcher on the start menu
this.launcher = {
text: "Admin Console",
iconCls:"icon-grid",
handler : this.createWindow,
scope: this
};
},

createWindow : function(){
var desktop, win;

desktop = this.app.getDesktop();
win = desktop.getWindow("admin-console") || this.createNewWindow(desktop);
win.show();
return win;
},

initController: function() {
Ext.each(this.controllers, function(control){
var controller = Iip.app.getController(control);
controller.init();
}, this);
},

createNewWindow: function(desktop) {
return desktop.createWindow({
layout: "border",
title: "Admin Console",
border: false,
id: "admin-console",
animCollapse:true,
iconCls: "icon-grid",
constrainHeader:true,
maximized: true,
items : [
{
xtype: "panel",
region: "west",
id: "admin-console-west-panel",
stateId: "navigation-panel",
title: "Admin Menu",
split: true,
width: 200,
minWidth: 175,
maxWidth: 400,
collapsible: true,
animCollapse: true,
margins: "0 0 0 5",
layout: "accordion",
items: this.getMenu(),
afterrender: this.initController()
},
Ext.create("Ext.tab.Panel", {
region: "center",
id: "admin-console-center-panel",
deferredRender: true,
activeTab: 0,
items: [
{
title: "Instruction",
autoScroll: true,
html: "<p>Viet<p/>"
}
]
})
]
});
},

getMenu: function() {
var menu = [];

$.ajax({
url: "index.php",
async: false,
dataType: "json",
data: {c: "get_admin_console_menu"},
success: function(data) {
if(data.success == true ) {
menu = data.menu;
}
}
});
return menu;
}
});

Here is my "Admin Console" controller file:

Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
console.log("controller init...");
this.control({
"Iip panel[region=west] #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});

vietits
28 Feb 2012, 3:57 PM
With your code, you should modify Iip.controller.iip.adm.AdminConsoles as below:


Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
console.log("controller init...");
this.control({
"window[id=admin-console] panel[region=west] #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});


However, I suggest you should use itemId instead of id as


createNewWindow: function(desktop) {
return desktop.createWindow({
layout: "border",
title: "Admin Console",
border: false,
//id: "admin-console",
itemId: "admin-console",
animCollapse:true,
iconCls: "icon-grid",
constrainHeader:true,
maximized: true,
items : [
{
xtype: "panel",
region: "west",
//id: "admin-console-west-panel",

itemId: "admin-console-west-panel",




In this case, your controller will become


Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
console.log("controller init...");
this.control({
"#admin-console #admin-console-west-panel #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});

phamtranquocviet
28 Feb 2012, 7:41 PM
Thanks vietits.

I tried both ways, and click event is still not fired. (By the way, I changed the window's id from console-admin to console-admin-window to avoid conflict with the view's id, which is console-admin)
The following shows that the "admin console" window does not even exist.



Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
var el = Ext.ComponentQuery.query("window");
console.log(el); => this line outputs an empty array

this.control({
"window[id=admin-console-window] panel[region=west] #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});


I am thinking my there is something wrong in having two namespaces, but I don't know how to fix this. My app's namespace is Iip, but the desktop's name space is MyDesktop. Below is the codes that creates the desktop after successful login inside my login controller.



Ext.define("Iip.controller.iip.Logins", {
extend: "Ext.app.Controller",
views: ["iip.Login"],
refs: [{selector: "login",ref: "loginViewRef"}],

handleFailedLogin: function(form, action) {
Ext.get("login-error").update("User not found");
},

loadDesktop: function(data) {
var myDesktopApp;

Ext.Loader.setPath({"Ext.ux.desktop": "app/view/iip/desktop/js", MyDesktop: "app/view/iip/desktop"});
Ext.require("MyDesktop.App");
Ext.getBody().mask("Loading desktop. Please wait...");

jsonData = JSON.parse(data);
Ext.onReady(function() {
Ext.create("MyDesktop.App", {
acl: jsonData.acl,
userFullName: jsonData.userFullName
});
Ext.getBody().unmask();
});
},

handleSuccessfulLogin: function(form, action) {
this.getLoginViewRef().close();
this.loadDesktop(action.response.responseText);
},

login: function(button) {
var form;

form = button.up("window").down("form");
form.submit({
params: {c: "login"},
success: this.handleSuccessfulLogin,
failure: this.handleFailedLogin,
scope: this
});
},

authenticate: function(button) {
// Input validation
if(button.up("window").down("form").getForm().isValid() == false ) {
return;
}

// Start authentication
this.login(button);
},

init: function() {
this.control({"login button[action=login]": {click: this.authenticate}});
}
});


Thanks vietits.

phamtranquocviet
28 Feb 2012, 7:55 PM
Thanks vietits.

I tried both ways, and click event is still not fired. (By the way, I changed the window's id from console-admin to console-admin-window to avoid conflict with the view's id, which is console-admin)
The following shows that the "admin console" window does not even exist.



Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
var el = Ext.ComponentQuery.query("window");
console.log(el); => this line outputs an empty array

this.control({
"window[id=admin-console-window] panel[region=west] #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});


I am thinking my there is something wrong in having two namespaces, but I don't know how to fix this. My app's namespace is Iip, but the desktop's name space is MyDesktop. Below is the codes that creates the desktop after successful login inside my login controller.



Ext.define("Iip.controller.iip.Logins", {
extend: "Ext.app.Controller",
views: ["iip.Login"],
refs: [{selector: "login",ref: "loginViewRef"}],

handleFailedLogin: function(form, action) {
Ext.get("login-error").update("User not found");
},

loadDesktop: function(data) {
var myDesktopApp;

Ext.Loader.setPath({"Ext.ux.desktop": "app/view/iip/desktop/js", MyDesktop: "app/view/iip/desktop"});
Ext.require("MyDesktop.App");
Ext.getBody().mask("Loading desktop. Please wait...");

jsonData = JSON.parse(data);
Ext.onReady(function() {
Ext.create("MyDesktop.App", {
acl: jsonData.acl,
userFullName: jsonData.userFullName
});
Ext.getBody().unmask();
});
},

handleSuccessfulLogin: function(form, action) {
this.getLoginViewRef().close();
this.loadDesktop(action.response.responseText);
},

login: function(button) {
var form;

form = button.up("window").down("form");
form.submit({
params: {c: "login"},
success: this.handleSuccessfulLogin,
failure: this.handleFailedLogin,
scope: this
});
},

authenticate: function(button) {
// Input validation
if(button.up("window").down("form").getForm().isValid() == false ) {
return;
}

// Start authentication
this.login(button);
},

init: function() {
this.control({"login button[action=login]": {click: this.authenticate}});
}
});


Thanks vietits.

vietits
28 Feb 2012, 11:00 PM
See my fix for your createNewWindow() method:


createNewWindow: function(desktop) {
return desktop.createWindow({
layout: "border",
title: "Admin Console",
border: false,
id: "admin-console",
animCollapse:true,
iconCls: "icon-grid",
constrainHeader:true,
maximized: true,
items : [{
xtype: "panel",
region: "west",
id: "admin-console-west-panel",
stateId: "navigation-panel",
title: "Admin Menu",
split: true,
width: 200,
minWidth: 175,
maxWidth: 400,
collapsible: true,
animCollapse: true,
margins: "0 0 0 5",
layout: "accordion",
items: this.getMenu(),
// afterrender: this.initController(), <- call this.initController() and assign returned value afterrender => mistake.
listeners: {
afterrender: this.initController
}
},
Ext.create("Ext.tab.Panel", {
region: "center",
id: "admin-console-center-panel",
deferredRender: true,
activeTab: 0,
items: [{
title: "Instruction",
autoScroll: true,
html: "<p>Viet<p/>"
}]
})
]
});
}

phamtranquocviet
1 Mar 2012, 8:17 PM
Thanks vietits...That gets me a little closer but not quite working yet. My selector now can find #acl. Here is it in the Firebug:
init...
[Object { initialConfig={...}, title="Access Control Manager", id="acl", more...}]

However, the expected log line "clicked..." is not showing in the Firebug. I will continue to try different things. If I find out the answer, I will definitely post it. Could you please shed some light?

Here is my controller again to make it easier for you to reference:


Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
console.log("init...");
var el = Ext.ComponentQuery.query("window[id=admin-console-window] panel[region=west] #acl");
console.log(el);

this.control({
"window[id=admin-console-window] panel[region=west] #acl": {
click: function() {
console.log("clicked...");
}
}
});
}
});

vietits
1 Mar 2012, 8:53 PM
What is xtype of component corresponding to "window[id=admin-console-window] panel[region=west] #acl"?

phamtranquocviet
1 Mar 2012, 9:00 PM
when I click on the found object ([Object { initialConfig={...}, title="Access Control Manager", id="acl", more...}]) in the Firebug, it says xtype is panel, and its alias is: widget.panel

vietits
1 Mar 2012, 11:38 PM
So you have to check your code again because panel does not have click event.

phamtranquocviet
2 Mar 2012, 5:44 AM
You are right, panel (in this case using accordion layout) does not have click event. I changed "click" event to "expand" and "collapse" events, and it worked like a charm. Here is the new code:


Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",

init: function() {
this.control({
"window[id=admin-console-window] panel[region=west] #acl": {
expand: function() {
console.log("expanded...");
},
collapse: function() {
console.log("collapsed...");
}
}
});
}
});


Now I have a more full-blown example to play with while doing more serious reading regarding to the internal working of the new class system.

Thanks you so much vietits. I am proud to have known a caring member like you.

phamtranquocviet
2 Mar 2012, 9:11 PM
vietis,

The getViewClassName() getter function does not appear in Firebug. Therefore, the call in blue below throws this error "getViewClassName is not a function". However, Firebug clearly shows that there is a property called "ViewClassName" in the config object in red. I have been pulling my hairs out for couple of hours now, and can't seem to be able to tell why. What am I missing?



Ext.define("Iip.controller.iip.adm.AdminConsoles", {
extend: "Ext.app.Controller",
view: ["iip.adm.AclTab"],
refs: [
{
ref: 'AdminConsoleMainTabPanel',
selector: 'window[id=admin-console-window] panel[region=center]'
}
],

openTab: function(panel, opts) {
console.log(panel); => Firebug shows the following:
/*
config Object { ViewClassName="Iip.view.iip.adm.AclTab"}
ViewClassName "Iip.view.iip.adm.AclTab"
*/
//However, getViewClassName() function does not appear in Firebug
var aclTab, adminConsoleMainTabPanel;

aclTab = Ext.ComponentQuery.query("acl-tab");
adminConsoleMainTabPanel = this.getAdminConsoleMainTabPanel();

if (aclTab.length == 0) {
aclTab = Ext.create(panel.getViewClassName(), {closable: true});
aclTab = adminConsoleMainTabPanel.add(aclTab);
adminConsoleMainTabPanel.setActiveTab(aclTab);
} else {
adminConsoleMainTabPanel.setActiveTab(aclTab[0]);
}
},

init: function() {
this.control(
{
"window[id=admin-console-window] panel[region=west] #acl": {
expand: this.openTab
},
"window[id=admin-console-window] panel[region=west] #test": {
expand: function() {
console.log("test clicked...");
}
}
}
);
}
});


panel.config.ViewClassName

vietits
2 Mar 2012, 10:59 PM
It seems that you've not initialized configuration for the panel #acl. Try to do this by calling initConfig() in the constructor of panel #acl.

phamtranquocviet
3 Mar 2012, 5:22 AM
vietits,
#acl is an item in my "Admin Console" view and is returned by function getMenu (in red), which gets an array (PHP code in green) from the server (in blue). I get it from the server to hide as much info as possible for security reasons.

Therefore, #acl does not have a constructor. Is this issue because the array returned by getMenu() is dynamic as opposed to static, which usually is the case for config?



Ext.define("Iip.view.iip.adm.AdminConsole", {
extend: "Ext.ux.desktop.Module",
controllers: ["Iip.controller.iip.adm.AdminConsoles"],
alias: "widget.admin-console",

// Create "Admin Console" menu item on start menu
init : function(){
// Define launcher on the start menu
this.launcher = {
...
handler : this.createWindow,
scope: this
};
},

createWindow : function(){
var desktop, win;

desktop = this.app.getDesktop();
win = desktop.getWindow("admin-console-window") || this.createNewWindow(desktop);
win.show();
return win;
},

initController: function() {
var controller;

controller = Iip.app.getController("Iip.controller.iip.adm.AdminConsoles");
controller.init();
this.initConfig();
},

createNewWindow: function(desktop) {
return desktop.createWindow({
...
maximized: true,
items : [
{
region: "west",
id: "admin-console-window-west-panel",
title: "Admin Menu",
split: true,
width: 200,
minWidth: 175,
maxWidth: 400,
collapsible: true,
animCollapse: true,
margins: "0 0 0 5",
layout: "accordion",
items: this.getMenu(),
listeners: {
afterrender: this.initController,
}
},
...
]
});
},

getMenu: function() {
var menu = [];

$.ajax({
url: "index.php",
async: false,
dataType: "json",
data: {c: "get_admin_console_menu"},
success: function(data) {
if(data.success == true ) {
menu = data.menu;
}
}
});
return menu;
}
});




echo json_encode(array(
"success" => true,
"menu" => array(
array("title" => "Access Control Manager",
"html" => "Use this menu to manage access control",
"id" => "acl",
"config" => array( "ViewClassName" => "Iip.view.iip.adm.AclTab" )
),
array("title" => "Test",
"html" => "Manage test",
"id" => "test"
),
)
));

vietits
3 Mar 2012, 6:55 AM
Because Panel has no config named 'config' so this will become a normal property of the #acl panel. So you should access panel.config.ViewClassName directly instead of calling to panel.getViewClassName() because it does not exist.

phamtranquocviet
7 Mar 2012, 7:18 PM
That works. Thanks vietits.