PDA

View Full Version : MVC comprehension problem



DLoT
27 Oct 2011, 6:38 AM
Hi,

I'am new to ExtJs and the MVC pattern and i have a little problem understanding why the following scenario don't work.

I've created an application that works like a windows desktop. The user can open different windows using shortcuts. If i open only one window of the same type all works fine, but if i open one more, the controlls aren't working properly.

I'am pretty sure that both windows using the same controller instance.

How do i create more than one instance of a controller?
Is this even possible or do i get the MVC pattern wrong?

greetz

Thomas

FoxMulder900
27 Oct 2011, 7:52 AM
You don't happen to have the 'id' property of the windows set to the same value do you? A conflict will occur when 2 instances are created with the same id.

If this isn't the case, post some code so we can get a better idea of your problem :)

dawesi
27 Oct 2011, 7:26 PM
good work mulder, the truth is out there! ;-) maybe it's in v4.2?!

DLoT
28 Oct 2011, 12:27 AM
I use the ExtJs ID's --> so no fixed ids for the windows.

I can post an example but i don't think it will help answering the question ;-)

for example i have a daterangeselector which i want to use across several windows.

The view -->



Ext.define('GUI.view.components.Daterangeselector' ,{
extend: 'Ext.Window',
alias : 'widget.daterangeselector',

title: gT('SELECT_DATERANGE'),
plain: true,
headerPosition: 'top',
width: 392,
height: 330,
maxDate:new Date(),
minDate:(13).days().ago(),
maximizable:false,
minimizable:false,
layout:'hbox',

initComponent: function() {
this.items=[{
xtype:'panel',
title:gT('FROM_DATE'),
margins:'5,5,5,5',
layout:'vbox',
height:255,
width:180,
items: [{
'xtype':'fromDatepicker',
maxDate:this.maxDate,
minDate:this.minDate

},{
'xtype':'fromTimepicker'
}]
},{
xtype:'panel',
title:gT('TO_DATE'),
margins:'5,5,5,5',
height:255,
width:180,
items: [{
'xtype':'toDatepicker',
maxDate:this.maxDate,
minDate:this.minDate
},{
'xtype':'toTimepicker'
}]
}]
this.bbar= [
{
xtype: 'daterangeSelected'
},
'-',
{
xtype: 'windowDateRangeText',
text:''
},
'-',
'->',
{
xtype: 'daterangeClose'
}
]
this.callParent();
}
});


The Controller -->


Ext.define('GUI.controller.components.Daterangeselector', {
extend: 'Ext.app.Controller',

fromTs:(13).days().ago(),
toTs:new Date(),
parentController:null,

init: function(parentController) {
this.parentController=parentController

this.addEvents('daterangechanged','daterangereload')
this.addListener({
daterangechanged:this.setDateRangeText
})

this.control({
'daterangeselector':{
render:this.initFields
},
'fromDatepicker':{
select:this.setFromTs
},
'toDatepicker':{
select:this.setToTs
},
'fromTimepicker timepickerHour':{
change:this.setFromTsHour
},
'fromTimepicker timepickerMinute':{
change:this.setFromTsMinute
},
'toTimepicker timepickerHour':{
change:this.setToTsHour
},
'toTimepicker timepickerMinute':{
change:this.setToTsMinute
},
'daterangeClose':{
click:this.closeDateRange
},
'daterangeSelected':{
click:this.fireReloadEvent
}
});
},
initFields:function(datePicker){
this.textField=datePicker.down('windowDateRangeText')
datePicker.down('fromDatepicker').setValue(this.fromTs)
datePicker.down('fromTimepicker timepickerHour').setValue(this.getFromTsHour())
datePicker.down('fromTimepicker timepickerMinute').setValue(this.getFromTsMinute())
datePicker.down('toTimepicker timepickerHour').setValue(this.getToTsHour())
datePicker.down('toTimepicker timepickerMinute').setValue(this.getToTsMinute())
},
setFromTs:function(field, fromTs){
this.fromTs=fromTs
this.fireEvent('daterangechanged')
},
getFromTs:function(format){
if(!format){
format='yyyy-MM-dd HH:mm:ss';
}
return this.fromTs.toString(format);
},
setFromTsHour:function(field, value){
if(value==0){
value=0;
}
this.fromTs.set({hour: value })
this.fireEvent('dateRangeChanged')
},
getFromTsHour:function(){
return this.fromTs.getHours()
},
setFromTsMinute:function(field, value){
if(value==0){
value=0;
}
this.fromTs.set({minute: value })
this.fireEvent('dateRangeChanged')
},
getFromTsMinute:function(){
return this.fromTs.getMinutes()
},
setToTs:function(field, toTs){
this.toTs=toTs
this.fireEvent('dateRangeChanged')
},
getToTs:function(format){
if(!format){
format='yyyy-MM-dd HH:mm:ss';
}
return this.toTs.toString(format);
},
setToTsHour:function(field, value){
if(value==0){
value=0;
}
this.toTs.set({hour: value })
this.fireEvent('dateRangeChanged',this)
},
getToTsHour:function(){
return this.toTs.getHours()
},
setToTsMinute:function(field, value){
if(value==0){
value=0;
}
this.toTs.set({minute: value })
this.fireEvent('dateRangeChanged',this)
},
getToTsMinute:function(){
return this.toTs.getMinutes()
},
setDateRangeText:function(){
this.textField.setText(this.getDateRangeString())
},
getDateRangeString:function(format){
if(!format){
format='dd.MM.yyyy HH:mm';
}
return '<b>'
+ this.getFromTs(format) + '</b> - <b>'
+ this.getToTs(format) +'</b>';
},
closeDateRange:function(btn){
btn.up('window').close()
},
fireReloadEvent:function(btn){
btn.up('window').close();
this.parentController.fireEvent('daterangeselected',{toTs:this.toTs,fromTs:this.fromTs});
}
})


and this is the code snippet from the parentcontroller



...
showDateRange:function(button){
var pos=button.getPosition(),
daterangeSelector=Ext.ComponentQuery.query('daterangeselector')[0] || null
if(daterangeSelector){
daterangeSelector.close();
}
this.getController('components.Daterangeselector').init(this);
var daterange = Ext.create('GUI.view.components.Daterangeselector',{
x: pos[0],
y: pos[1]-330,
showTimeSelector:true
});
daterange.show();
}
...


at the moment i close the daterange when it exists an rebuild it. it works but it's nasty... an other option would be creating a class the old fashioned way (i suppose), but i wan't to stick with the pattern.

so is there a way to create multiple instances of a controller?

greetz

FoxMulder900
28 Oct 2011, 6:15 AM
I may be misunderstanding the issue, if so forgive me.

I don't believe you can create multiple instances of the same controller (if you can I don't believe it is recommended in the MVC pattern).

Since this is the case I think you need to move anything that is 'instance specific' from the controller to your Daterangeselector class. So for example I think you would move this to Daterangeselector


fromTs:(13).days().ago(),
toTs:new Date(),




Then in your controller, take advantage of the fact that 'field'(aka the combo box) is passed to most of your events



setFromTs:function(field, fromTs){
var dateRangeSelectorInstance = field.up('daterangeselector');
dateRangeSelectorInstance.fromTs=fromTs;
this.fireEvent('daterangechanged'); // <-Probably want to add this listener to the daterangeselector class as well, then listen for it in the controller
},

FoxMulder900
28 Oct 2011, 6:18 AM
@dawesi - The truth is out there, but remember..... trust no one :)