Close Ext.Window from child html - extjs

I am new to ExtJS.
This is my window definition :
this.dialog = new Ext.Window({
title : "About us",
layout : 'anchor',
modal : true,
autoEl : {
tag : "iframe",
id: "myframe",
src : "../editor/actorseditor.html",
height: 500,
width : 600
} });
this.dialog.show();
I want to close my dialog window from "actorseditor.html".
How to achieve this. Also the opened window is not having close button.
Thanks in advance

This will only work if the html page in your iFrame is from the same application as your parent page. Or at least the protocol, subdomain, domain and port are all the same.
You will need to expose a global function in your parent page that will be called by the JavaScript running in the child page (iframe).
In your child page you call:
if (window.parent && window.parent.myGlobalFunction) {
window.parent.myGlobalFunction('hello!');
}
In your parent page you include the following global function (name it as you wish of course):
function myGlobalFunction(input){
console.log('message received:'+input);
MyApp.app.fireEvent('closeMyWindow',input);
}
This assumes that you are using MVC and you created property 'app' and set it to 'this' in the application launch function. And that you have a controller that is listening for aplication wide event like this:
Ext.define('MyApp.controller.Qnum', {
extend:'Ext.app.Controller',
init:function(){
this.control({
...
});
//listen for app wide event fired by : MyApp.app.fireEvent('closeMyWindow',input);
this.application.on({
closeMyWindow: this.closeWindowItsDrafty,
scope: this
});
},
closeWindowItsDrafty:function(){
//get reference to my window
//call myWindow.close();
}

I'll assume that in actorseditor.html, you must have a button
In this button you can set this listener:
listeners : {
click : function () {
Ext.getCmp('yourdialogid').close();
}
}
You also need to put an id to your dialog box.

Please try following inside your close button listener:
var parentDialogWindow = window.parent.Ext.cmp('ID_OF_DIALOG_WINDOW');
parentDialogWindow[parentDialogWindow.closeAction]();

Related

Add a Key Event Listener to a programmatically generated MessageBox using ExtJS4

I am building an ExtJS4 web application and there's a part there where I show a confirmation dialog to a user to confirm if the user wants to push through with the action. I use a programmatically generated MessageBox to ask the user and the user can click Yes or No.
Here is my code:
Ext.MessageBox.show({
title: alertHeader,
msg: alertMessage,
buttons: Ext.MessageBox.YESNO,
icon: Ext.MessageBox.WARNING,
cls: 'msgbox',
fn: function(btn){
//if user clicks yes, ask for override button
console.log('btn value = ' + btn);
if(btn ==='yes'){
//more code here
}
});
This works as intended, the program follows through with the appropriate actions based on the user selection (Yes or No). However, I want to add functionality wherein the user can simply press Y or N in the keyboard and the program will still execute as if Yes or No was actually pressed in the dialog.
However, I don't know how to go about adding a KeyEvent Listener to a MessageBox and the documentation is of little help.
Check Ext.util.KeyMap (and Ext.EventObject for key constants), also we have to set focus on our window to listen keyup events on it.
I create simple fiddle to illustrate how it works - Key map with message window.
Its not complete solution, but I guess rest you can do on your own.
As simple example you can do your logic directly on keypress and destroy myConfWindow or myConfWindow.down() to certain button and "click" it. But I guess that you want to use this message box in multiple places in your app, so its better to extend Ext.MessageWindow and add keymap there.
Attach this getKeyMapForKeyPressSubmit() method to your message box
'afterrender' : function() {
var map = this.getKeyMapForKeyPressSubmit();
}
And Method
getKeyMapForKeyPressSubmit : function (target, scope) {
var me = this;
return new Ext.util.KeyMap({
target : target,
binding : [{
key : 89, //Key for Y button - Ext.EventObject.Y
fn : function (key, e) {
//your logic for Yes button
}
}, {
key : 78, //Key for N button - Ext.EventObject.N
fn : function (key, e) {
//your logic for NO button
}
}
],
scope : scope
});
},
You can get a key map of MessageBox through getKeyMap. Add a new key listener to it in afterrender listener.
var myMsg = Ext.create('Ext.window.MessageBox', {
closeAction: 'destroy',
listeners: {
afterrender: function() {
this.getKeyMap().on(Ext.event.Event.Y, function() {
console.log("Yes");
}, this);
this.getKeyMap().on(Ext.event.Event.N, function() {
console.log("No");
}, this);
}
}
}).show({
title: 'Custom MessageBox Instance',
message: 'I can exist along with Ext.Msg'
});

ExtJs 4.1: Destroy components on closing a dynamically created tab

I am creating new ExtJs tabpanels and rendering panels inside it programmatically.
The panels (rendered inside tabs) are all written in separate JS files.
Opening, rendering and closing of the tabs is working completely fine.
But when I debug the code I see that the previous components of the closed tabs are still active in the memory. As a result of which the functioning of the components gets affected when the tab is reopened.
I want to destroy all the components inside the tab panels (if ExtJs, for some reasons, is not able to do it).
How can I do this?
Below is a sample code which I am trying:
Main Tab:
var tabs = new Ext.TabPanel({
id : 'screensTabPanel',
layout : 'fit',
enableTabScroll : true,
height : Ext.getBody().getStyleSize().height - 60,
activeTab : 0,
//enableTabScroll : true,
autoScroll : true,
autoRender : true,
border : false,
plugins : [ {
ptype : 'tabscrollermenu',
maxText : 30,
pageSize : 5
} ]
});
Dynamic Tab object:
var tabConfig = {
title : text,
bodyPadding : 3,
closeAction:'destroy',
autoScroll : true,
id : 'tab' + id,
closable : closable,
loader : {
loadMask : 'loading...',
autoLoad : true,
url : url,
scripts : true,
params : {
userId : 1
},
border : false,
appId : appIdx,
screenId : screenId,
gridType : gridType,
listeners : {
beforeclose : function(tab) {
debugger;
tab.removeAll(); //I tried doing this
tab.destroy(); //I tried doing this as well
return true;
}
}
};
Internal Panel code:
Ext.define('Ext.ux.window.VisualSQLQueryBuilder', {
extend: 'Ext.panel.Panel',
itemId: 'qb-VisualSQLQueryBuilderId',
renderTo: Ext.Element.get('divQueryBuilder'),
layout: {
type: 'border'
},
listeners:{
beforerender: function(thisa, eOpts ){
debugger;
/*if(Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId").length > 1){
Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId")[0].destroy();
}*/
Tab.MainTab = Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId")[Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId").length - 1];
}
},
items: [ .... screen components ... ]
});
Add Panel object to tab:
addedTab = ExtCont.add(tabConfig);
addedTab.show();
ExtCont.setActiveTab(addedTab);
Now this is what happens:
Open Tab (Name - Query Builder)
Code reaches the beforerender listener.
Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId") has only one object inside it.
Everything works fine.
Now the problem starts
Close the tab
Code reaches beforeclose listener. Trying tab.removeAll() and tab.destroy()
Reopen tab - Query Builder
Code reaches beforerender listener.
Now Ext.ComponentQuery.query("#qb-VisualSQLQueryBuilderId") has two objects inside it. So it is retaining the object of the tab opened first time. And the second one is that of the tab opened just now.
How do I ensure whenever a tab is closed all its components get smoothly destroyed?
from TabPanel:
Note: By default, a tab's close tool destroys the child tab Component and all its descendants. This makes the child tab Component, and all its descendants unusable. To enable re-use of a tab, configure the TabPanel with autoDestroy: false.
so it could really be an ExtJS Bug cause autoDestroy: true is default. maybe you could open a ticket.

How get html content from panel in ExtJs

I am new to ExtJs.
I have been facing a problem in panels for getting panel html content.
xtype : 'panel',
id : 'first_block',
html : '<p>Hi this is belongs to first block.</p>',
listeners : {
render : function(c) {
c.body.on('click', function() {
alert('' + this.id);
alert(Ext.getCmp('first_block').items.getAt(0).getValue());
});
}
I am not getting html content, but i am getting id like "first_block-body".
Thanks in advance.
The html property defined the HTML you want in the content of your component, in this case an Ext.Panel.
Ext.Panels create a few layers of divs in order to provide things like headers, footers, toolbars, etc.
If all you want is a div with some content, you instead want to use an Ext.Component. Components don't have a body, so a couple things change in your code.
xtype : 'component',
id : 'first_block',
html : '<p>Hi this is belongs to first block.</p>',
listeners : {
render : function(c) {
c.on('click', function() {
alert('' + this.id);
alert(this.el.dom.innerHTML);
}, this);
}
Notice that I added a third parameter to your on call, which specifies the this scope of the function call. I also edited your alert to print out the innerHTML of the element, assuming that's what you were trying to do.
UPDATE:
If you are going to use this component in a layout, it may need to be able to have its height and width set, meaning it needs to be of type box in order to be an Ext.BoxComponent.
Ext.getElementById('yourId').innerHTML

open html file on button click in Ext-JS4

I am running a html file in which when I click the submit button a new html file should open.
This is the code:
code running in loginForm.html
{
xtype : 'button',
text : ' Login ',
formBind : true,
listeners : {
click :function(){
alert();
//these methods are not working
//Ext.getCmp('login_panel').load({url : '/smartNav/pub/html/index_dev.html', scripts : true});
//Ext.getCmp('login_panel').update('index_dev.html');
}
}
}
Can someone suggest me how this can be done?
You can open new window just using window.open
window.open('/smartNav/pub/html/index_dev.html');
or change location in current window
window.location.href='/smartNav/pub/html/index_dev.html';

Why doesn't a simple click: function()... work in ExtJS?

When the user clicks on this element, I want it to show an alert.
However, when I click on the DIV that this Panel generates, nothing happens.
How can I make an alert execute when the user clicks on the following panel?
var content = new Ext.Panel({
region:'center',
margins:'5 0 5 5',
cls:'empty',
bodyStyle:'background:ivory; font-size: 13pt',
html:'<p id="test123">This is where the content goes for each selection.</p>',
click: function() {
alert('was clicked');
}
});
You haven't accepted an answer, so I'll assume you're still unclear on this. Here are a few pointers...
First, as coded your Panel will render as a plain square. If you're expecting it to look like a Panel, you should give it a title (so the title bar will render).
Second, as mentioned, click is not a Panel event (it's an Element event). So you have several ways of getting to the behavior you want. You can manually attach a listener to the underlying DOM element after the Panel is rendered:
Ext.get('txest123').on('click', function(){
alert('foo');
});
You could also do as I mentioned in the comments of another answer to generically handle any body click:
// .body is a Panel property for the body element
content.body.on('click', function(){
alert('foo');
});
If you really want to restrict the click to only the child p you could add a check:
// e is the event object, t is the target DOM node
content.body.on('click', function(e,t){
if(t.id == 'txest123'){
alert('clicked the p');
}
});
If I was coding this, I'd probably do something more like this:
var content = new Ext.Panel({
region:'center',
renderTo: document.body,
margins:'5 0 5 5',
cls:'empty',
title: 'My Panel',
id: 'txest123',
bodyStyle:'background:ivory; font-size: 13pt',
html:'This is where the content goes for each selection.',
listeners: {
'render': {
fn: function() {
this.body.on('click', this.handleClick, this);
},
scope: content,
single: true
}
},
handleClick: function(e, t){
alert(this.id); // the panel
alert(t.innerHTML); // the clicked el
}
});
Now the id is on the Panel (where it should be) and you can use Panel and/or Element methods to access child elements as needed. It's best to keep id's at the highest level possible. You'll notice too that the callback function is executed in the scope of the Panel (scope:this) so that inside handleClick you can treat this as the Panel itself and access any of its properties or methods.
So, without knowing exactly what you're trying to achieve, I can't provide you with the exact code you need. However, this should hopefully give you some ideas.
EDIT: I meant to say this originally... in your code (as posted) you are not actually rendering the Panel. As I mentioned in my answer to your related question, if you are adding the Panel as an item to a container that is lazy-rendered, the Panel's DOM won't be available for selection until after the container has rendered it. In my code above I added renderTo so that I don't have this issue, but if you're not doing that you'll have to wait until the Panel is rendered at some time later to access it.
The Panel Component does not expose a click event, so the one you're passing into the config never gets fired.
Try putting an id on your Ext.Panel object and then getting its element using Ext.get(). Then add a click event through on():
var content = new Ext.Panel({
id: 'myPanel',
region:'center',
margins:'5 0 5 5',
cls:'empty',
bodyStyle:'background:ivory; font-size: 13pt',
html:'<p id="txest123">This is where the content goes for each selection.</p>'
});
Ext.get('myPanel').on('click', function() {alert('You clicked me');});
The following sample is a bit rough but it works for me. It is a panel with a box component, which is showing a thumbnail. When clicking on the thumbnail, it is showing a lightbox with slimbox2. Not pretty, but very effective. The hardcoded images are just for test here.
var panel = new Ext.Panel({
title : 'Image',
header : false,
frame : true,
border : false,
bodyStyle : 'padding : 5px',
width : 125,
items : [{
xtype : 'box',
height : 115,
width : 115,
listeners : {
'render': function() {
var id = Ext.id(this);
Ext.fly(id).addListener('click', function () {
jQuery.slimbox('thisisnotanimage', 'CBX');
});
}
},
autoEl: {
tag : 'div',
html : 'somehtmltagstuff'
}
}
]
});
According to the API, click is not a valid event for Panels... However, you should still be able to add the click event to the underlying DIV element.
Ext.fly(e.id).addListener('click', Ext.getCmp(e.id) , this);
I believe you need something like:
var content = new Ext.Panel({
region:'center',
margins:'5 0 5 5',
cls:'empty',
bodyStyle:'background:ivory; font-size: 13pt',
html:'<p id="test123">This is where the content goes for each selection.</p>',
listeners: {
click: function() {
alert('was clicked');
}
}
});

Resources