I am attempting to launch a modal window from within a viewcontroller. Consider the following code (also located at https://fiddle.sencha.com/#fiddle/1335):
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.define('Window1',{
extend: 'Ext.window.Window',
controller: 'winctrl',
xtype: 'window1',
initComponent: function(){
Ext.apply(this,{
title:'Window 1',
width: 400,
height: 400,
layout: {type:'hbox',pack:'center',align:'middle'},
items:[{
xtype: 'button',
text: 'Click Me!',
handler: 'btnClickMeClick'
}]
});
this.callParent(arguments);
}
});
Ext.define('Window2',{
extend: 'Ext.window.Window',
xtype: 'window2',
initComponent: function(){
Ext.apply(this,{
title: 'Window 2',
width: 200,
height: 200,
modal: true,
//renderTo: Ext.getBody(),
layout: {type:'hbox',pack:'center',align:'middle'},
items:[{
html: 'Modal Looks Odd',
listeners:{
afterrender: 'htmlRender'
}
}]
});
this.callParent(arguments);
}
});
Ext.define('WinCtrl',{
extend: 'Ext.app.ViewController',
alias:'controller.winctrl',
btnClickMeClick: function(){
this.dialog = this.getView().add({xtype:'window2'});
this.dialog.show();
},
htmlRender: function(){
console.log(this.dialog);
}
});
Ext.widget('window1').show();
}
});
The problem I am running into is that when window 2 is launched it is modal only to the view that launched it and I need the window to be modal to the entire document. If run as is, the htmlRender function will log the window 2 object correctly. I attempted to set the renderTo: Ext.getBody() on window 2; however, I am unable to access it's object when it is rendered. In this case, htmlRender logs an "undefined" for the window 2 object.
I need some help allowing window 2 to be rendered as a modal to the document while allowing me to reference its object. Thanks for any help.
Don't add the window to that view, replace:
this.dialog = this.getView().add({xtype:'window2'})
With:
this.dialog = Ext.widget('window2');
Working example: https://fiddle.sencha.com/#fiddle/1338
I was able to work around this issue by setting the renderConfig:Ext.getBody() on window, removing the listener on the html item and adding a listener for the show event on window2: https://fiddle.sencha.com/#fiddle/133j
Related
Suppose we have defined a component (e.g. FieldSet) that we'd like to reuse in the single app (e.g. display/use it in 2 different modal windows.) This FieldSet has a reference, which we use to access it. The goal is to have these 2 windows contain independent fieldsets, so we can control and collect the inputs from each one separately.
Here's the sample fiddle that demonstrates the problem. As soon as any function triggers any lookupReference(...) call, Sencha issues the warning for "Duplicate reference" for the fieldset. It correctly creates two distinct fieldset components (by assigning different ids) on each window, but fails to properly assign/locate the references. As a result, any actions on one of these windows' fieldsets would be performed on the "unknown" one (probably on the first created one), messing up the UI behavior.
I see how it is a problem for Sencha to understand which component to use when operating on the reference, but there should be a way to reuse the same component multiple times without confusing the instances. Any help is greatly appreciated.
According to the docs on ViewController:
A view controller is a controller that can be attached to a specific view instance so it can manage the view and its child components. Each instance of the view will have a new view controller, so the instances are isolated.
This means that your use of singleton on your ViewController isn't correct, as it must be tied to a single view instance.
To fix this, I'd recommend making some modifications to your Fiddle, mainly removing the singleton: true from your VC class, accessing the views through lookup, and getting their VC's through getController to access your func method.
Ext.application({
name: 'Fiddle',
launch: function () {
/**
* #thread https://stackoverflow.com/questions/67462770
*/
Ext.define('fsContainerHandler', {
extend: 'Ext.app.ViewController',
alias: 'controller.fsContainerHandler',
// TOOK OUT singleton: true
func: function () {
var x = this.lookupReference('fsRef');
alert(x);
}
});
Ext.define('fsContainer', {
extend: 'Ext.container.Container',
xtype: 'xFSContainer',
controller: 'fsContainerHandler',
items: [{
xtype: 'fieldset',
title: 'myFieldset',
reference: 'fsRef'
}]
});
Ext.define('mainContainerHandler', {
extend: 'Ext.app.ViewController',
alias: 'controller.mainContainerHandler',
singleton: true,
onButton1Click: function () {
var win = this.getView().window1;
win.show();
// CHANGED LOGIC
win.lookup('theContainer').getController().func();
},
onButton2Click: function () {
var win = this.getView().window2;
win.show();
// CHANGED LOGIC
win.lookup('theContainer').getController().func();
}
});
Ext.define('mainContainer', {
extend: 'Ext.container.Container',
width: 400,
controller: 'mainContainerHandler',
window1: null,
window2: null,
initComponent: function () {
this.window1 = Ext.create('window1');
this.window2 = Ext.create('window2');
this.callParent(arguments);
},
items: [{
xtype: 'button',
text: 'Window 1',
reference: 'btn1',
handler: mainContainerHandler.onButton1Click,
scope: mainContainerHandler
}, {
xtype: 'button',
text: 'Window 2',
reference: 'btn2',
handler: mainContainerHandler.onButton2Click,
scope: mainContainerHandler
}]
});
Ext.define('window1', {
extend: 'Ext.window.Window',
title: 'Window1',
modal: true,
width: 100,
height: 100,
closeAction: 'hide',
// ADDED referenceHolder
referenceHolder: true,
items: [{
xtype: 'xFSContainer',
// ADDED reference
reference: 'theContainer'
}]
});
Ext.define('window2', {
extend: 'Ext.window.Window',
title: 'Window2',
modal: true,
width: 100,
height: 100,
closeAction: 'hide',
// ADDED referenceHolder
referenceHolder: true,
items: [{
xtype: 'xFSContainer',
// ADDED reference
reference: 'theContainer'
}]
});
Ext.create('mainContainer', {
renderTo: document.body
});
}
});
Following code
Ext.define('Fiddle.Panel', {
extend: 'Ext.Container',
layout: 'card',
items: [{
html: 'Check the console. Panel 2.1 fires activate event desipte the panel 1 being active',
xtype: 'panel',
listeners: {
activate: function (){
console.log('1 active');
}
}
},{
xtype: 'panel',
layout: 'card',
items: [{
xtype: 'panel',
// items: [... fieldpanel, fields here]
listeners: {
activate: function (){
console.log('2.1 active');
}
}
},{
xtype: 'panel',
listeners: {
activate: function (){
console.log('2.2 active');
}
}
}
}],
listeners: {
activate: function (){
console.log('2 active');
}
}
}]
});
Will immediately output.
1 active
2.1 active
I would like to focus a text field in the panel 2.1 on activation, but the event is fired even the field respectively whole 2.1 panel is not rendered yet as it is a child of inactive panel 2. Is this a feature or bug ? Should I use different approach ? Thank you for help.
Sencha Fiddle
https://fiddle.sencha.com/fiddle/39vc
Your two card layout panels (containers) will have an active item. So that is why they are both firing the activate event.
I would do the focus on the activeitemchange event and init. Here is a fiddle:
Fiddle
I had to do a defer in the init to be sure the field was rendered. there may be a better way to do this. See the buttons at the bottom to switch between the two panels.
We want to open a popup on click close(X) button of Main window and the window should open till we use confirm button.
The issue is main window hide(close) before confirm popup open and when we reopen main window then it is not showing and giving following error in console.
"Cannot read property 'show' of undefined"
Ext.define('Info.UI.Main Window',
{
extend: 'Ext.window.Window',
id: 'MyWindow',
modal: true,
title: 'Main Window',
closable: true,
closeAction: 'hide',
width: 515,
height: 705, //695,
layout: 'border',
bodyStyle: 'padding: 5px;',
listeners: {
save: function() {
},
//close main window when click X button
close: function() {
//alert("Open confirm window");
OpenConfirmationWindow();
}
}
});
For this you need to use beforeclose event of window. In beforeclose event you need to maintain one config to check confirmation of window will be close or not.
In this FIDDLE, I have create a demo using your code and put modification. I hope this will help or guide you to achieve your requirement.
Code Snippet
Ext.define('Info.UI.Main Window', {
extend: 'Ext.window.Window',
xtype: 'infoWindow',
modal: true,
title: 'This a new Window',
closable: true,
closeAction: 'hide',
width: 300,
height: 400,
layout: 'border',
bodyStyle: 'padding: 5px;',
listeners: {
save: function () {},
//beforeclose main window when click X button
beforeclose: function (thisWindow) {
if (!thisWindow.isConfirmed) {
Ext.MessageBox.confirm('Confirmation', 'Are you sure you wish to close this window before saving your changes?', function (btn) {
if (btn == 'yes') {
thisWindow.isConfirmed = true;
thisWindow.close();
}
});
return false;
}
}
}
});
Ext.create('Ext.panel.Panel', {
title: 'My Panel',
renderTo: Ext.getBody(),
items: [{
xtype: 'button',
margin: 20,
text: 'Open Info Wndow',
handler: function () {
//If window is already created then we can get using component query or Ext.getCmp();
var win = Ext.ComponentQuery.query('infoWindow')[0] || Ext.create('Info.UI.Main Window');
win.isConfirmed = false;
win.show();
}
}]
});
I have a Window class like this:
Ext.define('EMS.tf.alerts.alerts.view.AlertWindow', {
extend: 'Ext.window.Window',
alias: 'widget.ems-alerts-window',
height: 220,
width: 600,
alertTpl: undefined,
autoScroll: true,
selectedRecord: undefined,
title: undefined,
atext: undefined,
// #private
initComponent: function() {
var me = this;
Ext.apply(me, {
tpl: me.alertTpl,
listeners: {
show: function() {
Ext.create('Ext.Container', {
renderTo: 'alertContainer',
itemId: 'buttonContainer',
items : [{
xtype: 'button',
cls: 'ackbtn',
text : 'Acknowledge',
name: 'ackButton',
itemId: 'renderbutton'
},{
xtype: 'button',
cls: 'attchmntbtn',
text : 'Attachment',
name: 'attButton',
itemId: 'renderattachmntbutton'
}]
});
}
},
title: me.title
});
me.callParent();
}
});
I want to get reference to button "Attachment" using itemId "renderattachmntbutton". How to do this?
I tried windowobject.down('#renderattachmntbutton') but still it didn't work. I can get reference to the items placed before init function but not like this. Any idea on what needs to be done to get reference to this button?
That button is not an item (a child) of the window but of the button container. If you want to find it with down then you need to grab a reference to the container and call down on that.
Instead of
windowobject.down('#renderattachmntbutton') // WRONG
call
buttoncontainer.down('#renderattachmntbutton') // Correct
Try this
Ext.ComponentQuery.query('[itemId=renderattachmntbutton]')[0]
The itemId can be used with the getComponent() call on parent items, like container and panels. If you change your itemId on your container to just an id property. You can then get to your child items like so:
Ext.getCmp('buttonContainer').getComponent('renderattachmntbutton');
This is just one possible way, there are others!
You could try
windowobject.down('[itemId=renderattachmntbutton]') ;
i define a treeGrid with plugin CellEditing like
Ext.define('MyExample', {
extend: 'Ext.tree.Panel',
id: 'example',
alias: 'example',
....
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1,
listeners: {
beforeedit: function(plugin, edit){
alert('don't run second time');
}
}
})
],
...
And i have a button when i click this button will call below window (this window has treeGrid above)
Ext.create('Ext.window.Window', {
title: 'Phân xử lý',
modal:true,
height: 500
width: 500
layout: 'border',
...
item[
{
title: 'example',
region: 'center',
xtype: 'example', // that here
layout: 'fit'
}
]
Everything working at first time but when i close the window at first time and click button to call window again then CellEditting still working but listeners not working ?
How to fix that thanks
EDIT
Please see my example code in http://jsfiddle.net/E6Uss/
In first time when i click button. Everything working well like
But when i close Example window and open it again I try click to blocked cell again i get a bug like
How to fix this bug? thanks
The problem here is that you are using Ext.create inside the plugins array for the tree grid. This have the effect of creating it once and attaching the result adhoc to your defined class.
If you close the window, all the resources within the window are destroyed. The second time you instantiate the tree panel, the plugin is not there. Take a look at this fiddle : I see what your issue is. Take a look at http://jsfiddle.net/jdflores/E6Uss/1/
{
ptype : 'cellediting',
clicksToEdit: 1,
listeners: {
beforeedit: function(plugin, edit){
console.log('EDITOR');
if (edit.record.get('block')) {
alert('this cell have been blocked');
return false;
}
}
}
}
You're recreating the window on every click of the button. This recreation may be messing with your configuration objects or destroying associations or references within them, or something similar. Try to reuse the window everytime by replacing your button code with something like:
Ext.create('Ext.Button', {
text: 'Click me',
visible: false,
renderTo: Ext.getBody(),
handler: function(button) {
if(!button.myWindow)
{
button.myWindow = Ext.create('Ext.window.Window', {
title: 'Example',
height : 300,
width : 500,
layout: 'border',
closeAction: 'hide',
items: [{
region: 'center',
floatable:false,
layout:'fit',
xtype: 'example',
margins:'1 1 1 1'
}
]
});
}
button.myWindow.show();
}
});
Maybe it needed complete the editing cell, try finish it:
...
beforeedit: function(plugin, edit){
alert('don't run second time');
plugin.completeEdit();
}
Sencha: CompleteEdit
I put together a working example here: http://jsfiddle.net/jdflores/6vJZf/1/
I think the problem with your column is that it's dataIndex is expecting that the editor value be a boolean type (because 'block' was set as datIndex instead of 'date'). I assume you are using the 'block' field just to identify which are blocked to be edited. I modified the fidle provided here: http://jsfiddle.net/jdflores/6vJZf/1/
{
text: 'Block Date',
dataIndex: 'date',
xtype: 'datecolumn',
format: 'd/m/Y',
editor: {
xtype: 'datefield',
allowBlank: true,
format: 'd/m/Y'
}
}