Way to render any component in extjs on fly - extjs

I am provided with built in extjs components classes.
I cannot change them as i am working on plugin.
I cannot override them as there are certain things which cannot be
predefined.
And also I want to change component for particular case, not all
cases.
Now If it will be possible that I pick that component from DOM,
change it any of property and render it there onwards. If it could
be done, then my work become lot easy.
Its completely a scenario. But still for ease in understanding, I am adding a sample code.
var tabPanel = Ext.create('Ext.tab.Panel', {
width : 300,
height : 200,
activeTab : 0,
items : [
{
title : 'Tab1',
bodyPadding : 10,
items : [
{
xtype : 'button',
text : 'B1'
}
]
},
{
title : 'Tab2',
items : [
{
xtype : 'button',
text : 'B2'
}
]
}
],
renderTo : Ext.getBody(),
autoRender : true
});
// Change title of tab panel
tabPanel.items.each(function(item) {
item.title = "text"+Math.random();
});
Now I want to remove this already rendered tab panel. And want to render it upon my choice wherever i want.

After lot of search, I find solution to problem. We can use doLayout() or update() function of component to fulfill purpose.

Related

Extjs - override collapse function

i'm new of Extjs; i have a panel with the item "collapsible: true" and it works fine but...
when my specific condition is true, i want to collapse the panel, and i want to disable the button used to expand it (therefore the panel doe not show anymore, even if the click is made).
It's possible do it?
I want a type of override method that doing other things, for example to show a div with few specific information in the page.
I use only javascript and Extjs.
thanks in advance and happy holidays
I added a bindable version
Fiddle
Using databinding to collapsible, you might also add the binding to the collapsed param
Please see my snippet. Can it resolve your issue ? Tell me if you have any question.
https://fiddle.sencha.com/fiddle/1fk9
Ext.application({
name : 'Fiddle',
launch : function() {
var parent = Ext.create('Ext.container.Container', {
title : 'Demo',
renderTo : Ext.getBody(),
layout : 'vbox',
items : [{
xtype : 'checkbox',
fieldLabel : 'Enable collapsible',
handler : function(self, v){
var panel = parent.down('panel');
panel.collapseTool.setVisible(v);
panel.getHeader().down('tool[type=up]').setVisible(!v);
},
checked : true
}, {
xtype : 'panel',
width : 500,
height : 400,
title : 'Collapsible demo',
collapsible : true,
tools : [{
type : 'up',
hidden : true
}]
}]
});
}
});

The right event to apply "scrollTo" to show a dynamically added nested panel

I have a panel in ExtJS6 modern (mobile) application that can scroll vertically only. Sub panels are added dynamically to it. I need to scroll the panel to its end after adding a new sub-panel in order to make it visible. This is done using this line:
Ext.getCmp('tabmainMessagesPanel').getScrollable().scrollTo(Infinity, Infinity, true);
I execute this line in a button click, and it works (but need to click the button manually). I tried to find the right event where I can add this line to do the scroll automatically, without success. I nearly tried all the possible relevant events of the sub-panel: show, add, added, activate, ... I also tried the events of the parent panel without success.
Apparently, these events happen before the scroller of the parent panel takes into account the added sub-panel, so it scrolls to the before-last one. I smell asynchronous behavior here. The proof is that I call the scrollTo method in a delayed task of 0.5 second and it works. But this solution is not reliable.
The question is: where (in which event of which component) this line of code should go in order to scroll the parent to its end correctly?
[EDIT]
Here is the part of the code concerning the question. First, the Message class:
Ext.define('MyApp.view.message.Message', {
extend : 'Ext.Panel',
xtype : 'message',
layout : 'hbox',
config : {
mBody : ''
},
listeners: {
added: function (element) {
MyApp.view.main.Global.scroller.delay(500); //start a delayed task to scroll parent panel
}
},
items: [
{
flex : 1
},
{
maxWidth: '80%',
width: 'auto',
html : '<div class="myClass">' + this.getMBody() + '</div>'
}
]
});
Here is the delayed task that scrolls the parent panel tabmainMessagesPanel to its end in order to show the newly-added message:
Ext.define('MyApp.view.main.Global', {
statics: {
scroller: Ext.create('Ext.util.DelayedTask', function() {
Ext.getCmp('tabmainMessagesPanel').getScrollable().scrollTo(Infinity, Infinity, true);
})
}
}
Now, the tab panel that contains the panel tabmainMessagesPanel that will contain the messages:
Ext.define('MyApp.view.main.TabMain', {
extend : 'Ext.tab.Panel',
mixins : [ 'Ext.mixin.Responsive' ],
xtype : 'tabmain',
responsiveConfig : {
portrait : {
items :
[
{
title : 'Messages',
layout : 'vbox',
items : [ {
xtype: 'panel',
layout : 'vbox',
height: '100%',
id: 'tabmainMessagesPanel',
scrollable : 'vertical',
style : 'background-color:#F0F0F0'
},
{
xtype : 'inputfield',
docked : 'bottom'
}]
},
{
title : 'Connect',
layout: 'vbox',
items : [
//some UI elements
]
}
]
},
//--------------------------------------------------
landscape : {
// same as portrait
}
},
//--------------------------------------------------
controller : 'tabmain',
viewModel : 'tabmain',
defaults : {
tab : {
iconAlign : 'top'
},
styleHtmlContent : true
}
});
Finally, this is an event in a controller that creates and adds a message to tabmainMessagesPanel whenever a new message arrives:
handle_message: function (mess) {
var p = Ext.create('MyApp.view.message.Message', {
mBody : mess.body
});
Ext.getCmp('tabmainMessagesPanel').add(p);
}
Here is the answer for this. I found it 6 months later. I post it here for the benefit of those who may have the same issue.
The solution is to define the event refresh of the scroller of the panel tabmainMessagesPanel, and scroll to the end in it. So, the definition of the panel tabmainMessagesPanel becomes:
{
xtype: 'panel',
layout : 'vbox',
height: '100%',
id: 'tabmainMessagesPanel',
scrollable : 'vertical',
listeners: {
initialize: function (me) {
me.getScrollable().on('refresh', function () {
me.getScrollable().scrollTo(Infinity, Infinity, true);
});
}
},
style : 'background-color:#F0F0F0'
}

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.

custom component reuse with extjs4

I have created a custom grid in a javascript file. I want to use it as a xtype on to different panels in seperate js files. If I use it on a single panel, it works fine; but when I use try it use it on different panels at the same time, I get a error in the chrome developer tool console saying:
Uncaught TypeError: Cannot read property 'isComponent' of undefined
My grid definition is as follows:
Ext.define('DataBox.view.FootNotes', {
extend : 'Ext.grid.Panel',
alias : 'widget.footNotes',
initComponent : function() {
this.columns = [ {
header : 'SL',
field : {
xtype : 'checkbox',
checked : 'true'
}
}, {
header : 'Symbol',
}, {
header : 'Notes',
}, ];
this.callParent(arguments);
}
});
and to include the grid on the panels i use following code
initComponent : function() {
/* this.footNotesInfoGrid = Ext.create('DataBox.view.FootNotes', {
colspan: 2,
border: false,
frame: 'false'
}); even tried this */
Ext.apply(this,{
items : [{
xtype : 'footNotes',
columnWidth : .50,
id : 'infoFootNotesGrid',
}]
}
}
I tried many other ways suggested on different forum discussions.. but my problem stil persists.
Can somebody point out where I am going wrong?
Don't assign created objects within a configuration! Use initComponent for that!
this line
plugins : [ Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit : 1
}) ],
should be placed as
this.plugins = [ Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit : 1
}) ];
anywhere in the initComponent body, but before callParent is called
Edit:
to still allow override do
if(!this.plugins) {
this.plugins = [ Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit : 1
}) ];
}
Edit
Avoid using static id properties! The framework handle that part for you. Wrap your head around Ext.ComponentQuery instead. It will help you to find any Component you are looking for.

Menu item in Ext-JS4

I am new to Ext-JS4. I am working on a project in which I am configuring a toolbar. I have added few buttons to the toolbar, one of which has a menu and the menu basically has a grid which is loaded from a JSON store. The grid is used within the menu due to such requirement in the project. The grid is loaded properly but I need access to the menu item being clicked within the menu. I want the text of the menu item which is clicked. The following code will better explain my question.
var store = Ext.create('Ext.data.Store', {
storeId : 'favStore',
model : favModel,
autoLoad : true,
groupField : 'group_header',
proxy : {
type : 'ajax',
url : '../../data/favorites.json',
reader : {
type : 'json',
root : 'favoritesMenu'
}
}
});
var favGrid = Ext.create('Ext.grid.Panel', {
store : store,
columns : [{
dataIndex : 'listItem',
width : 200
}],
features : [groupingFeature],
width : 200,
height : 275,
autoHeight : true,
border : false
});
var favMenu = Ext.create('Ext.menu.Menu', {
items : [favGrid],
listeners : {
'click' : function(store,item) {
alert('Item clicked= ');//tried item.text here but not working
}
}
});
In the alert method on the click event I want the text of the menu item clicked. I hope I am clear with the question. Can anyone give me some suggestions? Also can anyone suggest me some good blogs on Ext-JS4?
All these things are defined within the initComponent method of Ext.define() for toolbar.
You can use the documentation.
For me it was very usefull:
http://docs.sencha.com/ext-js/4-0/
I believe in your case you want the listener to be attributed to your grid, not the menu. Something like...
var favGrid = Ext.create('Ext.grid.Panel', {
store : store,
columns : [{
dataIndex : 'listItem',
width : 200
}],
features : [groupingFeature],
width : 200,
height : 275,
autoHeight : true,
border : false,
listeners: {
'itemclick': function(view, record, item, index, e, eOpts){
//Assuming 'name' is a fieldname in the record
alert('item clicked = ' + record.get('name'));
}
}
});
Check out the Ext.grid.Panel documentation here: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel . Click on "events" at the top and find "itemclick".
or you can have your menu listen to the grid's event by relaying the events.
favMenu.relayEvents(favGrid, ['itemclick']);
favMenu.on('itemclick', me.onFavFunction, me);

Resources