Related
I've a resizable panel which includes another panel with hbox layout inside. Whole display settings are correct expect one behaviour; when resizing main panel with mouse after render; it's not auto-fit items inside.
To be success fit those item; need to resize main panel once again or refreshing main panel from tool config's gear. How can I set this mouse event resizing as auto-fit?
Here is a screenshot and both of panel's code snippets;
Main Panel:
Ext.define('MyApp.BasePanel', {
extend: 'Ext.panel.Panel',
xtype: 'basepanel',
resizable: true,
scrollable: true,
frame: true,
plugins: 'responsive',
tools: [
{
type: 'refresh',
handler: 'refreshPanel'
},
{
type: 'gear',
handler: 'setPanel'
}
],
initComponent: function() {
var me = this;
me.items = me.setupItems();
me.callParent();
},
setupItems: function() {
var me = this;
return Ext.Array.merge(me.getChildPanel(), me.getOtherChildPanel());
},
getChildPanel: function () {
return [];
},
getOtherChildPanel: function () {
return [];
},
Here is called child panel;
Ext.define('MyApp.ChildComponent', {
//Calling this class with 'getChildPanel()' method on BasePanel.
extend: 'Ext.container.Container',
alias: 'widget.mychildcomponent',
layout: {
type: 'hbox', align: 'stretch', pack: 'center'
},
defaults: {
margin: 10,
width: 300,
height: 90,
flex: 1
},
items: [
{
How can I set this mouse event resizing as auto-fit
You need to use flex config for ExtJS child items to automatically adjust.
Flex
Flex may be applied to child items of a box layout (Ext.layout.container.VBox or Ext.layout.container.HBox). Each child item with a flex property will fill space (horizontally in hbox, vertically in vbox) according to that item's relative flex value compared to the sum of all items with a flex value specified.
Any child items that have either a flex of 0 or undefined will not be 'flexed' (the initial size will not be changed).
In this Fiddle, I have created a demo using resizable panel.
Code snippet
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('CommonGrid', {
extend: 'Ext.grid.Panel',
xtype: 'commongrid',
title: 'Data',
store: {
fields: ['name', 'email', 'phone'],
data: [{
name: 'Lisa',
email: 'lisa#simpsons.com',
phone: '555-111-1224'
}, {
name: 'Bart',
email: 'bart#simpsons.com',
phone: '555-222-1234'
}, {
name: 'Homer',
email: 'homer#simpsons.com',
phone: '555-222-1244'
}, {
name: 'Marge',
email: 'marge#simpsons.com',
phone: '555-222-1254'
}]
},
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}]
});
Ext.create({
xtype: 'panel',
layout: 'vbox',
title: 'Demo',
bodyPadding: 10,
width: 500,
border: true,
resizable: true,
draggable: true,
tools: [{
type: 'refresh'
}, {
type: 'settings'
}],
renderTo: Ext.getBody(),
defaults: {
layout: 'hbox',
xtype: 'container',
width: '100%',
flex: 1,
defaults: {
xtype: 'button',
margin: '0 10',
flex: 1
}
},
items: [{
maxHeight:30,
items: [{
text: 'Button 1'
}, {
text: 'Button 2'
}, {
text: 'Button 3'
}]
},{
xtype:'tbspacer',
height:10,
maxHeight:10
}, {
items: [{
xtype: 'commongrid'
}, {
xtype: 'commongrid'
}]
}]
})
}
});
This happens because the default layout for all Containers is Auto Layout
Make BasePanel layout hbox or vbox and if you want it to be scrollable do not set align
I have a form panel with a radiogroup, and depending on the radiogroup selection, it will show some other components. If a radiofield is not selected, then its items will be hidden, as they're not part of the active card.
Now, if I have allowblank: false set on a field (and it's empty) within the hidden card, my form is still considered invalid. Being hidden means the user would not like to use it, so it should not be considered as part of the form. Here's an example.
In the example, I have 2 forms... the top form is the one that I'm curious about... is there a way to get this working without having to bind to disabled? I tried looking at hideMode, but that wasn't what I was looking for.
Ideally, I wouldn't have to create a formula for each card that I add... that seems silly. I realize I could create a generic formula, but once again, that just seems extraneous. Another option could be ditching the card layout, and binding each card to hidden and disabled, but I'm creating more formulas. Is there some sort of property I'm missing?
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.define('MyController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myview',
onValidityChange: function(form, isValid, eOpts) {
this.getViewModel().set('isFormValid', isValid);
}
});
Ext.define('MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myview',
data: {
activeItem: {
myInput: 0
}
},
formulas: {
activeCardLayout: function(getter) {
var myInput = getter('activeItem.myInput');
console.log(myInput);
return parseInt(myInput);
}
}
});
Ext.define('MyForm', {
extend: 'Ext.form.Panel',
title: 'My Form',
controller: 'myview',
viewModel: {
type: 'myview'
},
layout: {
type: 'hbox'
},
listeners: {
validitychange: 'onValidityChange'
},
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
layout: {
type: 'hbox'
},
items: [{
xtype: 'button',
text: 'Save',
reference: 'saveButton',
disabled: true,
bind: {
disabled: '{!isFormValid}'
}
}]
}],
items: [{
xtype: 'radiogroup',
vertical: true,
columns: 1,
bind: {
value: '{activeItem}'
},
defaults: {
name: 'myInput'
},
items: [{
boxLabel: 'None',
inputValue: '0'
}, {
boxLabel: 'Something',
inputValue: '1'
}]
}, {
xtype: 'container',
layout: 'card',
flex: 1,
bind: {
activeItem: '{activeCardLayout}'
},
items: [{
xtype: 'container',
layout: 'fit'
}, {
xtype: 'container',
layout: 'fit',
items: [{
xtype: 'textfield',
fieldLabel: 'hello',
allowBlank: false
}]
}]
}]
});
Ext.define('MyViewModel2', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myview2',
data: {
activeItem: {
myInput: 0
}
},
formulas: {
disableSomethingCard: function(getter) {
return getter('activeItem.myInput') !== '1';
},
activeCardLayout: function(getter) {
var myInput = getter('activeItem.myInput');
console.log(myInput, 'here');
return parseInt(myInput);
}
}
});
Ext.define('MyForm2', {
extend: 'MyForm',
title: 'My Form 2 (works)',
viewModel: {
type: 'myview2'
},
items: [{
xtype: 'radiogroup',
vertical: true,
columns: 1,
bind: {
value: '{activeItem}'
},
defaults: {
name: 'myInput'
},
items: [{
boxLabel: 'None',
inputValue: '0'
}, {
boxLabel: 'Something',
inputValue: '1'
}]
}, {
xtype: 'container',
layout: 'card',
flex: 1,
bind: {
activeItem: '{activeCardLayout}'
},
items: [{
xtype: 'container',
layout: 'fit'
}, {
xtype: 'container',
layout: 'fit',
bind: {
disabled: '{disableSomethingCard}'
},
items: [{
xtype: 'textfield',
fieldLabel: 'hello',
allowBlank: false
}]
}]
}]
});
Ext.create('MyForm', {
renderTo: Ext.getBody()
});
Ext.create('MyForm2', {
renderTo: Ext.getBody()
});
}
});
I have tabpanel, which contains a few tabs. I will be concentrating on the 6th tab here - navigatingPanels.js file. In this file, I have a card layout, so that the user can fill form1 & move to form2 on submission (slide to form2). I also have a docked toolbar, with a back button, so that the user can move back to form1 (if needed). It gives an error -
Uncaught Error: [ERROR][Ext.Base#callParent] Invalid item given: undefined, must be either the config object to factory a new item, or an existing component instance.
The app can be seen here - http://maalguru.in/touch/Raxa-70/MyApp/
Update - If I add one extra card to the concerned panel, & remove the form1 & form2 (required panels/cards), then it works fine. In this case I have to setActiveItem to the desired cards (form1 & form2). Changed Viewport - http://pastebin.com/P4k04dBQ
Is there any solution to achieve with only 2 panels/cards ?
Viewport.js
Ext.define('MyApp.view.Viewport', {
extend: 'Ext.TabPanel',
xtype: 'my-viewport',
config: {
fullscreen: true,
tabBarPosition: 'bottom',
items: [{
xclass: 'MyApp.view.navigatingPanels'
}]
}
});
NavigatingPanels.js
Ext.define('MyApp.view.navigatingPanels', {
extend: 'Ext.Panel',
id: 'navigatingPanels',
xtype: 'navigatingPanels',
config: {
iconCls: 'user',
title: 'Navigating Panels',
layout: 'card',
animation: {
type: 'slide',
direction: 'left'
},
defaults: {
styleHtmlContent: 'true'
},
items: [{
docked: 'top',
xtype: 'toolbar',
title: 'Registeration Form',
items: [{
text: 'Back',
ui: 'back',
align: 'centre',
//back button to take the user back from form2 to form1
handler: function() {
Ext.getCmp('navigatingPanels').setActiveItem(form1);
}
}]
},
form1,
form2
]
}
});
var form1 = new Ext.Panel({
scrollable: 'vertical',
items: [{
xtype: 'fieldset',
title: 'Form 1',
items: [{
xtype: 'textfield',
label: 'Name',
name: 'name',
},
{
xtype: 'button',
text: 'Save Data & move to form2',
ui: 'confirm',
//TODO add some action: to store data
//save data & move to form2
handler: function() {
Ext.getCmp('navigatingPanels').setActiveItem(form2, {
type: 'slide',
direction: 'right'
});
console.log("Form1");
}
}
]
}]
});
var form2 = new Ext.Panel({
scrollable: 'vertical',
items: [{
xtype: 'fieldset',
title: 'Form 2',
items: [{
xtype: 'textareafield',
label: 'Message',
name: 'message'
},
{
xtype: 'button',
text: 'Submit Data',
ui: 'confirm',
//TODO add some action: to store data
//action: 'Submit Data'
}
]
}]
});
App.js
Ext.Loader.setConfig({
enabled: true
});
Ext.application({
name: 'MyApp',
controllers: ['Main'],
launch: function() {
Ext.create('MyApp.view.Viewport', {
fullscreen: true
});
}
});
Finally I got the answer. The component instances should not be given as items in Ext.define, instead their config should be given. The setActiveItem can be called the the normal way -
Ext.getCmp('navigatingPanels').setActiveItem(0);
CODE SNIPPET
Ext.define('MyApp.view.navigatingPanels', {
extend: 'Ext.Panel',
id: 'navigatingPanels',
xtype: 'navigatingPanels',
config: {
iconCls: 'user',
title: 'Navigating Panels',
layout: 'card',
animation: {
type: 'slide',
direction: 'left',
duration: 300
},
defaults: {
styleHtmlContent: 'true'
},
items: [{
docked: 'top',
xtype: 'toolbar',
title: 'Registeration Form',
items: [{
text: 'Back',
ui: 'back',
align: 'centre',
//back button to take the user back from form2 to form1
handler: function() {
Ext.getCmp('navigatingPanels').setActiveItem(0, {
type: 'slide',
reverse: 'true',
duration: '300'
});
console.log(Ext.getCmp('navigatingPanels'));
}
}]
},
{
xtype: 'fieldset',
title: 'Form 1',
scrollable: 'vertical',
items: [{
xtype: 'textfield',
label: 'Name',
name: 'name',
},
{
xtype: 'button',
text: 'Save Data & move to form2',
ui: 'confirm',
//TODO add some action: to store data
//save data & move to form2
handler: function() {
Ext.getCmp('navigatingPanels').setActiveItem(1, {
type: 'slide',
direction: 'right'
});
console.log("Form1");
}
}
]
},
{
scrollable: 'vertical',
items: [{
xtype: 'fieldset',
title: 'Form 2',
items: [{
xtype: 'textareafield',
label: 'Message',
name: 'message'
},
{
xtype: 'button',
text: 'Submit Data',
ui: 'confirm',
//TODO add some action: to store data
//action: 'Submit Data'
}
]
}]
}
]
}
});
Try this...
myNavigationPanel = Ext.create('MyApp.view.navigatingPanels');
myNavigationPanel.setActiveItem(0);
Ext.define('MyApp.view.Viewport', {
extend: 'Ext.TabPanel',
xtype: 'my-viewport',
config: {
fullscreen: true,
tabBarPosition: 'bottom',
items: [{
xclass: 'MyApp.view.Home'
},
{
xclass: 'MyApp.view.Contact'
},
{
xclass: 'MyApp.view.Products'
},
{
xclass: 'MyApp.view.Forms'
},
{
xclass: 'MyApp.view.NestedTabPanels'
},
myNavigationPanel
]
}
});
I'm trying to implement a simple framework for an app. The idea is to create a background viewport type 'layout' with a north region containing the page header and an interchangeable center region.
When my app starts, a Login form is shown. If the user/password is ok, the form is destroyed and the main layout should appear. The main layout should insert a nested layout in its center region.
This is my background layout code:
Ext.define('DEMO.view.BackgroundLayout', {
extend: 'Ext.container.Viewport',
alias: 'widget.background',
requires: [
'DEMO.view.Main'
],
layout: {
type: 'border'
},
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
region: 'north',
html: '<h1 class="x-panel-header">Page Title</h1>'
},
{
xtype: 'mainview',
region: 'center',
forceFit: false,
height: 400
}
]
});
me.callParent(arguments);
}
});
The main layout is this:
Ext.define('DEMO.view.Main', {
extend: 'Ext.container.Viewport',
alias: 'widget.mainview',
requires: [
'DEMO.view.MyGridPanel'
],
layout: {
type: 'border'
},
initComponent: function() {
var me = this;
console.log('bb');
Ext.applyIf(me, {
items: [
{
xtype: 'mygridpanel',
region: 'center',
forceFit: false
},
{
xtype: 'container',
height: 38,
forceFit: false,
region: 'north',
items: [
{
xtype: 'button',
height: 34,
id: 'btnLogout',
action: 'logout',
text: 'Logout'
}
]
}
]
});
me.callParent(arguments);
}
});
As you can see, the center region needs an xtype named "mygridpanel". This is the code for it:
Ext.define('DEMO.view.ui.MyGridPanel', {
extend: 'Ext.grid.Panel',
border: '',
height: 106,
title: 'My Grid Panel',
store: 'MyJsonStore',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
viewConfig: {
},
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'Id',
text: 'Id'
},
{
xtype: 'gridcolumn',
dataIndex: 'Name',
text: 'Name'
},
{
xtype: 'gridcolumn',
dataIndex: 'Sales',
text: 'Sales'
}
],
dockedItems: [
{
xtype: 'toolbar',
dock: 'top',
items: [
{
xtype: 'button',
disabled: true,
id: 'btnDelete',
allowDepress: false,
text: 'Delete'
},
{
xtype: 'button',
disabled: true,
id: 'btnEdit',
allowDepress: false,
text: 'Edit'
}
]
}
]
});
me.callParent(arguments);
}
});
My problem is that when I call Ext.create('DEMO.view.BackgroundLayout', {}); it only shows the nested layout, and the background layout is hidden, also I get this error in Chrome's console:
Uncaught Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
What I'm doing wrong?.
Thanks in advance,
Leonardo.
I would like to say that Im struggling with understanding the portal demo in ExtJS 4. Can someone please just provide me a generic example of a container and how to add a portlet item. The docs provided with the download do not have the word portal or portlet when I do the search. When I look at the source of the example there are classes files and extra CSS files too. Are those needed? I have searched all over the web and only seem to find other people asking the same question. Any help or even a link to a demo for extjs 4 would be greatly appreciated. Maybe my googlefoo is lacking?
When I use the demo and start modifying the border layout I run into all sorts of issues. The center region cannot contain a tab panel, I use accordion layouts for my east, west, and north regions. There seems to be an issue with the West region and having an accordion layout because it does not display properly ie. the accordion is like half open and any images inside do not display unless you collapse and then re-open. Would someone be able to provide me with an example that just shows how to make a basic portal without any added functionality? Below is the code I was using that was not working properly but displays and works fine (except for the portal part) when using just a viewport.
Here is some example code
Ext.define('Ext.app.Portal', {
extend: 'Ext.container.Viewport',
uses: ['Ext.app.PortalPanel'],
initComponent: function(){
Ext.apply(this, Ext.create('Ext.Viewport', {
id: 'main-viewport',
layout: {
type: 'border',
padding: '0 5 5 5'
},
items: [{
title: 'My Notifications',
id: 'My-Notifications-Panel',
region: 'north',
height: 300,
split: true,
collapsible: true,
collapsed: true,
margins: '0 0 0 0',
layout: 'accordion',
items: [
{
title: 'Alerts'
},{
title: 'Communications'
}
]
},{
title: 'My Support',
id: 'My-Support-Panel',
region: 'east',
width: 140,
collapsible: true,
collapsed: true,
margins: '0 0 0 0',
layout: 'column',
autoScroll: true,
defaults: {
margins: '10 5 0 0',
xtype: 'panel',
height: 100,
width: '100%',
headerPosition: 'bottom',
border: false,
cls: 'myicon',
bodyStyle: 'background-image: url(images/icon.png); background-repeat: no-repeat; background-position: center;'
},
items:[
{
title: 'Customer Services'
},{
title: 'Technical Support',
listeners: {
afterrender: function(c){
c.el.on('click', function(){
CreateChatSession();
Ext.getCmp('My-Support-Chat-Panel').update('<iframe width="100%" height="700" src="/pub/" frameborder="0"></iframe>');
});
}
}
}
]
},{
xtype: 'panel',
region: 'west',
collapsible: true,
collapsed: true,
title: 'My Apps',
width: 275,
layout:'accordion',
split: true,
margins: '0 0 0 0',
defaults: {
bodyStyle: 'padding:15px',
layout: 'column'
},
items: [{
title: 'Internal Apps',
defaults: {
padding: '5 5 5 5',
xtype: 'panel',
height: 100,
width: 80,
headerPosition: 'bottom',
border: false,
cls: 'myicon',
bodyStyle: 'background-image: url(images/icon.png); background-repeat: no-repeat; background-position: center;'
},
items: []
},{
title: 'Favorites',
defaults: {
padding: '5 5 5 5',
xtype: 'panel',
height: 100,
width: 80,
headerPosition: 'bottom',
border: false,
cls: 'myicon',
bodyStyle: 'background-image: url(images/icon.png); background-repeat: no-repeat; background-position: center;'
},
items: []
},{
title: 'Reporting',
defaults: {
padding: '5 5 5 5',
xtype: 'panel',
height: 100,
width: 80,
headerPosition: 'bottom',
border: false,
cls: 'myicon',
bodyStyle: 'background-image: url(images/icon.png); background-repeat: no-repeat; background-position: center;'
},
items: []
}]
},
Ext.create('Ext.tab.Panel', {
region: 'center',
layout: 'fit',
items: [{
id: 'Workspace-1',
title: 'Workspace 1',
layout: 'fit',
items: [{
id: 'app-portal',
xtype: 'portalpanel',
region: 'center',
items: [{
id: 'col-1',
items: [{
id: 'portlet-2',
title: 'Portlet 2',
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
},{
id: 'col-2',
items: [{
id: 'portlet-3',
title: 'Portlet 3',
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
}]
}]
}]
})
]
}));
this.callParent(arguments);
}
});
----------- Just for anyone who reads this Portal Layout IS NOT part of the official framework and is a 3rd party extension bundled with the library, which is why it is not in the docs.
It'ss the portal example with tabs in center region
Hope this will help you.
Ext.define('Ext.app.Portal', {
extend: 'Ext.container.Viewport',
getTools: function() {
return [{
xtype: 'tool',
type: 'gear',
handler: function(e, target, panelHeader, tool) {
var portlet = panelHeader.ownerCt,
el = portlet.getEl();
el.mask('Working...');
Ext.defer(el.unmask, 2000, el);
} //eo handler function
}]; //eo return
}, //eo get tools
initComponent: function() {
var content = '<div class="portlet-content">' + Ext.example.shortBogusMarkup + '</div>';
Ext.apply(this, {
id: 'app-viewport',
layout: {
type: 'border',
padding: '0 5 5 5'
}, //eo layout
items: [{ //header : item 1 of app-viewport
id: 'app-header',
xtype: 'box',
region: 'north',
height: 50,
html: 'myPortal'
},
{ //container : item 2 of app-viewport
xtype: 'container',
region: 'center',
layout: 'border',
items: [{ //options: item 1 of container
id: 'app-options',
title: 'Options',
region: 'west',
animCollapse: true,
width: 200,
minWidth: 150,
maxWidth: 400,
split: true,
collapsible: true,
layout: 'accordion',
layoutConfig: {
animate: true
},
items: [{ //item 1 of app-options
title: 'title',
autoScroll: true,
border: false,
iconCls: 'nav',
items: [{
xtype: 'treepanel',
useArrows: true,
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
border: false,
region: 'west',
split: true,
listeners: {
click: function(n) {
Ext.Msg.alert('Navigation Tree Click', 'You clicked: "' + n.attributes.text + '"');
}
}
/*Dashboard
MultiServices
Reporting
Global Options
*/
}]
},
{ //settings : item 2 of app-options
title: 'Settings',
html: '<div class="portlet-content">' + 'details ??' + '</div>',
border: false,
autoScroll: true,
iconCls: 'settings'
}
] //eo items options
},
{ //item 2 of container
id: 'tabpanel1', // id: 'app-portal', ???
xtype: 'tabpanel',
activeTab: 0,
region: 'center',
items: [{
title: 'tab1',
layout: 'column', //
closable: true,
items: [{
id: 'col-1',
columnWidth: 0.5,
flex: 1,
items: [{
id: 'portlet-1',
title: 'Grid Portlet',
tools: this.getTools(),
items: new Ext.app.GridPortlet(),
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}, {
id: 'portlet-2',
title: 'Portlet 2',
tools: this.getTools(),
html: content,
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}] //eo col-1
}, {
id: 'col-2',
columnWidth: 0.5,
flex: 1,
items: [{
id: 'portlet-3',
title: 'Portlet 3',
tools: this.getTools(),
html: '<div class="portlet-content">' + Ext.example.bogusMarkup + '</div>',
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}] //eo col-2
}, {
id: 'col-3',
columnWidth: 0.5,
flex: 1,
margins: '0 26 0 0',
items: [{
id: 'portlet-4',
title: 'Chart Portlet',
tools: this.getTools(),
items: new Ext.app.ChartPortlet(),
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}] //eo col-3
}] //eo tab1
}, {
title: 'tab2',
closable: true
}] //eo items tabpanel
}
] //eo ietms container
}
] //eo viewport
}); //eo apply
this.callParent(arguments);
}, //eo initcomponent
onPortletClose: function(portlet) {
this.showMsg('"' + portlet.title + '" was removed');
},
showMsg: function(msg) {
var el = Ext.get('app-msg'),
msgId = Ext.id();
this.msgId = msgId;
el.update(msg).show();
Ext.defer(this.clearMsg, 3000, this, [msgId]);
},
clearMsg: function(msgId) {
if (msgId === this.msgId) {
Ext.get('app-msg').hide();
}
}
});
EDIT
Or u can try this example I think it suits better ur needs ,let me know.