Panel inside a Panel: autoScroll not working - extjs

I have this view (DetailsContainer, first class in code section of this question) with two items inside (MetaDataPanel, Preview), but autoscroll doesn't work in MetaDataPanel (follow the code).
So when I put some items inside MetaDataPanel, autoscroll doesn't work...
PS: the content of MetaDataPanel is generated dinamically adding element to this Panel...
Any suggests?
Ext.define('DP.view.DetailsContainer' ,{
id: 'DetailsContainer',
extend: 'Ext.Panel',
alias : 'widget.DetailsContainer',
collapsible: true,
// margins:'5 0 5 5',
split:true,
layout: {
type: 'accordion',
align: 'stretch',
pack : 'start'
},
initComponent: function() {
Ext.apply(this, {
items: [{
xtype: 'MetaDataPanel',
flex:1
},{
xtype: 'Preview',
flex:2
}]
});
this.callParent(arguments);
}
});
Ext.define('DP.view.MetaDataPanel' ,{
id: 'MetaDataPanel',
extend: 'Ext.Panel',
alias : 'widget.MetaDataPanel',
title : 'MetaDati',
layout: 'fit',
autoScroll:true, //TODO: autoscroll not working
initComponent: function() {
Ext.apply(this, {
items: [{
xtype: 'component' ,
html: 'Nessun File o Cartella selezionata. Selezionare un elemento per visualizzare i metadati!',
margin: 5,
style: {
color: '#000000'
}
}]
});
this.callParent(arguments);
}
});

It doesn't make sense to specify autoScroll on a container with a fit layout. The child will always fit the size of the container, it will never be bigger, so you can never scroll. You want the autoScroll on the inner component.

I don't think it make sense for an accordion panel to scroll. What you should do instead is set the inner component to to scroll. Look at your code slightly changed to reflect that idea:
http://jsfiddle.net/dbrin/jmHEj/

Most easy (or lazy) is to set config autoScroll as a default - so that it will be inherited:
defaults: {autoScroll: true},

Related

Implementing a Routing system for my Views (ExtJS)

I want to implement a route for my basic view in ExtJS so that when display it (on a button click) the URL changes and when i want to return back to the initial view it works by displaying the right view.
Giving my view class :
Ext.define('Traccar.view.newDashboard', {
extend: 'Ext.Container',
alias: 'widget.newDashboard',
id: 'geoAfricaDashboard',
routes : {
'dashboard' : ''
},
layout: {
type: 'border',
align: 'stretch '
},
height: 620,
style: {
'backgroundColor': '#909090 !important'
},
items: [{
// xtype: 'panel' implied by default
title: 'Geo-Africa Administration',
region: 'west',
xtype: 'panel',
//margin: '5 0 0 5',
width: 200,
collapsible: true, // make collapsible
id: 'west-region-container',
layout: 'fit',
items: [{
xtype: 'treelist',
store: {
root: {
expanded: true,
children: [{
text: 'Options',
leaf: true,
iconCls: 'fas fa-address-book'
}, {
text: 'Administration',
expanded: true,
iconCls: 'far fa-id-badge',
children: [{
text: 'Configuration',
leaf: true,
iconCls: 'fas fa-address-card'
}, {
text: 'User',
leaf: true,
iconCls: 'fas fa-child'
}]
}]
}
},
renderTo: Ext.getBody()
}]
}, {
xtype: 'basic-panels'
// width: '100%'
}]
Which i render on button click like so :
var dash = Ext.create('widget.newDashboard', {
renderTo: Ext.getBody(),
hideMode: 'visibility'
});
dash.show();
How can i assign a route URI to that view in ExtJS (6.2.0)?
Thank you for the great help ?
PS : i tried with
routes : {
'dashboard' : ''
},
or else this.redirectTo("dashboard"); But neither works.
The route is similar to firing an event. The end result is a function is called. The hash is passed to the function based on how the route is setup. You can either call a different function for each hash or you can use the hash, or other parts of the URI to determine what to do.
Router Documentation This web page describes how the router is used. It is a very quick read.
A common way the examples (admin dashboard, coworkee app) do it by having the hash be the xtype for the panel (view) you want to display.
So your main panel extends 'Ext.navigation.View'. Then based on the hash you create a new instance of the view, add it to the main panel and make it the active item. You can also check to see if the xtype has already been added to the navigation view and just make it the active panel.
Fiddle showing use of router (this is not mine). Here is a fiddle that shows how to use a router. I would recommend reading the docs first. THe sencha docs are actually pretty good and you can learn how to use the Extjs library as it was intended and really speed up your development.

Run same code in each tab in extjs

I wish to have the same form panel in each tab of the tabbed pannel. Is there a way that the same code is run for each tab without having to copy the code in the items list since that would be redundant.
Here is one way to do it -
You'll normally define a tabpanel and you give multiple panels as an array of items. For each of the panel inside the item, give the same panel container that you define below as the item.
{
xtype: 'tabpanel',
itemId: 'myTabPanel',
activeTab: 0,
plain: true,
items: [{
xtype: 'panel',
itemId: 'tab1',
layout: 'fit',
title: 'Strategies',
items: [{
xtype: 'myTabContainer'
}],
tabConfig: {
xtype: 'tab',
closable: false
}
}, {
xtype: 'panel',
itemId: 'tab2',
layout: 'fit',
title: 'Action Sets',
items: [{
xtype: 'myTabContainer'
}]
}],
listeners: {
tabchange: 'tabChangeListener' // define this and handle the actions for your tab change event
}
}
And here is a sample definition of the container/content for the tab. You can note that I'm using the alias for this container "myTabContainer" as xtype in each of the tabs above. This will make sure that the same view is linked to both the tabs.
Ext.define('MyTabContainer', {
extend: 'Ext.panel.Panel',
alias: 'widget.myTabContainer',
requires: [
// give all required classes
],
viewModel: {
type: 'dfstrategiesmaincontainer'
},
itemId: 'tabContent',
layout: 'border'
// Define all other required items and contents
}
Define a form and set that form as an item in each tab.
//Define the form
Ext.define('App.view.MyForm', {
extend:'Ext.form.Panel',
alias: 'widget.myform',
bodyPadding:10,
items: [....]
});
//Use the form as an item in each tab
Ext.create('Ext.tab.Panel', {
width: 400,
height: 400,
renderTo: document.body,
items: [{
title: 'Tab1',
xtype: 'myform'
}, {
title: 'Tab2',
xtype: 'myform'
}]
});

Get reference to itemId in Extjs

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]') ;

textfields collapsed after sencha cmd build

I am using the lastest sencha cmd for the build with ext-5.0.1.
Everythings look good during the development status (http://www.imageupload.co.uk/5Med) but after the build.
All the textfields collapsed like shown (http://www.imageupload.co.uk/5MeQ), and have no response to the changes in width, minWidth, flex... etc.
And also the properties y and x are not functioning.
If someone had had similar situation before, please help, thx
My cmd is v5.0.3.324
Here are part of my code:
In my Main.js:
Ext.define('ExtTest2.view.main.Main', {
extend: 'Ext.container.Container',
requires: [
'ExtTest2.view.main.MainController',
'ExtTest2.view.main.MainModel'
],
xtype: 'app-main',
controller: 'main',
viewModel: {
type: 'main'
},
layout: {
type: 'fit'
},
itemId:'Stage'
});
MainController.js:
Ext.define('ExtTest2.view.main.MainController', {
extend: 'Ext.app.ViewController',
requires: [
],
alias: 'controller.main',
init: function(){
this.Start();
},
Start: function(){
var data = {
itemId: "Page_Login",
xtype: "panel",
items: [
{
padding: 30,
layout:{
type: 'vbox',
align: 'center'
},
xtype: "fieldset",
y: "30%",
height: 150,
items: [
{
xtype: "textfield",
itemId: "Textfield_Username",
fieldLabel: "用戶名稱",
labelStyle: "color:#FFFFFF"
},
{
fieldLabel: "密碼",
itemId: "Textfield_Password",
labelStyle: "color:#FFFFFF",
xtype: "textfield"
},
{
itemId: "Button_Login",
text: "登入",
width: 100,
xtype: "button"
}
]
}
]
};
var container = Ext.ComponentQuery.query('#Stage')[0];
container.removeAll();
container.add(data);
container.updateLayout();
}
});
It is overnested because you add unnecessary container to app-main containing the fields.
It is very unusual to manipulate views from view controller like that - create a class for the fieldset, give it an alias (xtype) and simply instantiate that. Cramming controller handlers together with view definitions shall inevitably lead to Spaghetti Code.
You use vbox layout, without any flex or height to hold form fields. Form fields behave best in anchor layout that is the default for Ext.form.Panel.

Extjs: Reuse the same grid in TabPanel

in a Extjs application I have a Grid and a Tabs line over it. Content of the Grid depends on the selected Tab.
Say tabs has Jan-Feb-Mar-... values. Clicking of the Tab I would reload grid's store
Question: is it possible to avoid duplicating of the 12 grid components in favor to have one shared instance?
Thanks
Disclaimer: searching at the sencha's forum, google, stackoverflow was not successful :(
It is, but it would require more effort than it is worth. Just create a prototype for your component, so that you can create new instances really quickly.
I haven't tried this myself, but I imagine that you could create a TabPanel with empty tabs and size the TabPanel so that only the tab strip is visible. Under that (using the appropriate layout, border, vbox, etc.) create your GridPanel and use the TabPanel's activate event to reload the grid based on the currently-active tab.
Hope the following implementation meet your needs
1. Create your custom grid and register it
2. place it tab panel
As the grid is created using xtype, it would not create 12 instances when you change tabs.
Application.PersonnelGrid = Ext.extend(Ext.grid.GridPanel, {
border:false
,initComponent:function() {
Ext.apply(this, {
store:new Ext.data.Store({...})
,columns:[{...}, {...}]
,plugins:[...]
,viewConfig:{forceFit:true}
,tbar:[...]
,bbar:[...]
});
Application.PersonnelGrid.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
,onRender:function() {
this.store.load();
Application.PersonnelGrid.superclass.onRender.apply(this, arguments);
} // eo function onRender
});
Ext.reg('personnelgrid', Application.PersonnelGrid);
var panel = new Ext.TabPanel({
items:[{
title:'Jan',
items: [{xtype:'personnelgrid'}]
}, {
title: 'Feb',
items: [{xtype:'personnelgrid'}]
}
....
{
title: 'Dec',
items: [{xtype:'personnelgrid'}]
}]
})
Since this is the only place discussed about this until now, I share what I just found.
The trick is use dockedItems in ExtJs 4 (Not sure either grid can be added into tbar in ExtJs 3)
When changing the active tab, only body will be change but not the docked item. Just set the grid height equal to the body during boxready and resize so that we can't see the body anymore.
This is the code for ExtJs 4.2 MVC that also make use of refs.
Ext.define('app.controller.Notification', {
extend: 'Ext.app.Controller',
views: ['notification.List'],
stores: ['Notification'],
models: ['Notification'],
refs: [{
ref: 'pnlNotif',
selector: 'pnlNotif'
}, {
ref: 'notifList',
selector: 'notifList'
}],
init: function () {
this.control({
'dbPnlNotif': {
added: this.pnlNotifAdded,
boxready: this.calcNotifListSize,
resize: this.calcNotifListSize,
tabchange: this.pnlNotifTabChange
}
});
},
pnlNotifAdded: function (pnlNotif) {
pnlNotif.add({ title: '1', html: '1' });
pnlNotif.add({ title: '2', html: '2' });
pnlNotif.add({ title: '3', html: '3' });
},
calcNotifListSize: function (pnlNotif) {
// calc the notification list height to make sure it use the whole body
// This way we can use only one instance of list to display for each tabs
// because the list is rendered as dockedItems
var height = pnlNotif.getHeight();
var headerHeight = pnlNotif.getDockedItems()[0].getHeight();
var tabBarHeight = pnlNotif.getDockedItems()[1].getHeight();
height = height - headerHeight - tabBarHeight;
if (this.getNotifList().getHeight() !== height) {
this.getNotifList().setHeight(height - 1);// - 1 to include border bottom
}
},
pnlNotifTabChange: function (pnlNotif, newTab) {
// do something to filter the list based on selected tab.
}
});
Ext.define('ML.view.Notification', {
extend: 'Ext.tab.Panel',
alias: ['widget.pnlNotif'],
title: 'Notification',
dockedItems: [{
xtype: 'notifList'
}]
});
Ext.define('ML.view.notification.List', {
extend: 'Ext.grid.Panel',
alias: 'widget.notifList',
dock: 'top',
store: 'Notification',
initComponent: function () {
this.columns = [
...
];
this.callParent(arguments);
}
});
Try this
var gridJanName = Ext.create('Ext.grid.Panel', {
enableColumnHide: false,
autoScroll:true,
store: storeJanNameGroup,
border:true,
stripeRows: true,
columnLines:false,
loadMask: true,
tbar:tbgridTools,
margin: '1 1 1 1',
pageSize: 100,
maxWidth:700,
features: [groupFeature],
selModel: {
mode: 'MULTI'
},
columns: [
{xtype:'rownumberer',width:50},
{dataIndex:'id', hidden:true},
//etc
]
});
var gridFebName = Ext.create('Ext.grid.Panel', {
enableColumnHide: false,
autoScroll:true,
store: storeJanNameGroup,
border:true,
stripeRows: true,
columnLines:false,
loadMask: true,
tbar:tbgridTools,
margin: '1 1 1 1',
pageSize: 100,
maxWidth:700,
features: [groupFeature],
selModel: {
mode: 'MULTI'
},
columns: [
{xtype:'rownumberer',width:50},
{dataIndex:'id', hidden:true},
//etc
]
});
//
//etc grid
//
var JanPanel = Ext.create('Ext.panel.Panel', {
title:'Jan',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
},
items: [gridJanName]
});
var FebPanel = Ext.create('Ext.panel.Panel', {
title:'Feb',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
}
//,items: [gridFebName]
});
var MarPanel = Ext.create('Ext.panel.Panel', {
title:'Mar',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
}
//,items: [gridMarName]
});
//etc
var eachMonthstabs = Ext.create('Ext.tab.Panel', {
minTabWidth: 130,
tabWidth:150,
//Width:750,
scroll:false,
autoHeight: true,
id:'timestabs',
enableTabScroll:true,
items: [
{
xtype:JanPanel
},
{
xtype:FebPanel
},
{
xtype:MarPanel
}
///etc
]
});
For me good solution was to use a left toolbar called lbar with list of buttons and a single grid instead of tabpanel

Resources