I am using ExtJs 4.0.7 and I have just got into a problem.
I want to resize the elements in the form(panel) when I resize the window which contains it(or them).
It's simple when you don't have columns and you are using an anchor layout, I know.
So far, my code looks like this:
initComponent: function ()
{
var me = this;
me.terminalImage = Ext.create('Ext.Img', {
src: 'http://www.sencha.com/img/20110215-feat-html5.png',
width: 50,
margin: '0 10 0 0'
});
me.nameField = Ext.create('Ext.form.Text', {
xtype: 'textfield',
name: 'defname',
fieldLabel: 'myFLabel',
allowBlank: false,
listeners: {
}
});
me.terminalTypeCmb = Ext.create('Ext.form.field.ComboBox', {
fieldLabel: me.getTrans('lblTerminalType.Text', 'Type'),
parentRecord: me.parentRecord,
store: 'myStore',
queryMode: 'local',
name: 'typename',
width: 300,
valueField: 'deftype',
displayField: 'typename',
listeners: {
}
});
me.form = Ext.create('Ext.form.Panel', {
xtype: 'form',
autoScroll: true,
defaultType: 'textfield',
defaults: { layout: 'anchor', flex: 1},
padding: '10',
items: [{
xtype: 'container',
layout: 'hbox',
items: [
me.terminalImage,
{
items: [me.nameField, me.terminalTypeCmb]
}
]
}
]
});
Ext.apply(this,
{
defaults: {
},
defaultType: 'textfield',
items: [me.form]
});
if (me.parentRecord)
{
me.form.loadRecord(me.parentRecord);
}
this.callParent(arguments);
}
I wanted to get something like that:
My Image | My TextField (resizable width on window resize)
(fixed size) | My ComboBox (I know it is not resizable)
|
Right now, my textfield remains with a constant width on window resize. Thank you for your help.
you are almost there :)
just remove default flex :defaults: { layout: 'anchor', flex: 1}, // not sure if you need the layout.
and add flex:1 only to the TextField.
Having the other items with fixed with, will make the TextField take all the space left.
Related
I have a list of images that I can choose from, and each one of them has different dimensions. In order to maintain aspect ratio, I'm only setting the width on the image, so the browser determines which height the image should be given. Unfortunately, because I don't have a height, Ext JS is unsure what height to give the container, so it doesn't update it after the first image is rendered.
In the example below, you'll see the first image renders properly and sets the height of the panel's body. If you select the other image in the combobox, it won't set the height, and it'll be cut off. However, if you uncomment the bodyCls property, and re-run the example, it will behave as it should... the image selection changes the height of the panel dynamically.
This seems a little hacky to me, and I don't like using float: left directly, but I want these items to be laid out in an hbox fashion, so I'm wondering if there's a better way of accomplishing this. Does someone have a better solution?
And no, I don't want to use object-fit or background-size: cover;
Here's the Fiddle and code:
Ext.application({
name: 'Fiddle',
launch: function () {
var f = Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
border: true,
bodyStyle: 'border-color: blue !important;',
height: 'auto',
referenceHolder: true,
// layout: {
// type: 'hbox',
// columns: 2
// },
// layout: 'fit',
defaults: {
style: 'float: left;'
},
// This style add height: 100% to the body
// bodyCls: 'blah',
margin: 5,
bodyPadding: 5,
viewModel: {
stores: {
logosStore: {
autoLoad: true,
proxy: {
url: 'data1.json',
type: 'ajax'
}
}
}
},
items: [{
xtype: 'image',
width: 200,
reference: 'blah',
hidden: true,
bind: {
src: '{record.logoSrc}',
hidden: '{!record.logoSrc}'
}
}, {
xtype: 'combobox',
valueField: 'logoFileId',
displayField: 'name',
queryMode: 'local',
forceSelection: true,
margin: '0 0 0 40',
value: 2,
listConfig: {
itemTpl: '<img src="{logoSrc}" style="max-height: 40px;" />'
},
bind: {
store: '{logosStore}',
selection: '{record}'
},
listeners: {
select: function (combo, record) {
f.getViewModel().notify();
// f.setHeight(f.lookupReference('blah').getHeight());
// f.lookupReference('blah').getEl().dom.setAttribute('background-image', 'url("' + record.get('logoSrc') + '")');
}
}
}]
})
}
});
EDIT
My solution starts to break down when you have my component being used in another container with several other components. See this Fiddle, but it works if you uncomment the cls property in the MyForm component... just seems wrong that I have to add height: 100% !important to everything. Like maybe there's a layout that I could use instead.
I did come up with a solution, and that was to employ a little bit of JavaScript... I basically wait for the image to load, grab the current height of the image, and update the maxHeight of its container, so it can report its height back to its parent container. The one odd thing is, if the maxHeight is below a certain threshold, I want to keep it at 150, and if the threshold is hit twice or more, when I do setMaxHeight(150), it doesn't actually update the height of the image. That's why I setMaxHeight(null) first if the threshold hasn't been met. An example of this was when I selected the 2nd image first, and then the 3rd image... the 3rd image would be cut off if I didn't setMaxHeight(null).
I think this is an acceptable solution, but once again, I'm wondering if there's a layout that'll do this for me, or I'm not understanding a certain layout or nesting components.
Fiddle and code:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyForm', {
extend: 'Ext.form.Panel',
alias: 'widget.myForm',
border: true,
bodyStyle: 'border-color: blue !important;',
referenceHolder: true,
scrollable: true,
layout: 'fit',
margin: 5,
bodyPadding: 5,
tools: [{
xtype: 'button'
}],
viewModel: {
stores: {
logosStore: {
autoLoad: true,
proxy: {
url: 'data1.json',
type: 'ajax'
}
}
}
},
items: [{
xtype: 'container',
reference: 'blah2',
scrollable: true,
height: 150,
maxHeight: 150,
layout: {
type: 'hbox'
},
items: [{
xtype: 'image',
width: 200,
reference: 'blah',
hidden: true,
bind: {
src: '{record.logoSrc}',
hidden: '{!record.logoSrc}'
},
listeners: {
el: {
load: function () {
f.getViewModel().notify();
var blah2 = f.lookupReference('blah2');
var height = f.lookupReference('blah').getHeight();
if (height < 150) {
height = 150;
blah2.setMaxHeight(null);
}
console.log(blah2.setMaxHeight(height), height);
}
}
}
}, {
xtype: 'combobox',
valueField: 'logoFileId',
displayField: 'name',
queryMode: 'local',
forceSelection: true,
margin: '0 0 0 40',
value: 2,
width: 350,
listConfig: {
itemTpl: '<img src="{logoSrc}" style="max-height: 40px;" />'
},
bind: {
store: '{logosStore}',
selection: '{record}'
}
}]
}]
});
var f = Ext.create('MyForm', {
renderTo: Ext.getBody()
});
}
});
I have this code:
Ext.define('innerWindow', {
extend: 'Ext.window.Window',
title: 'title',
height: 200,
width: 500,
modal: true
});
tb = Ext.getCmp('head-toolbar');
tb.add({
text: 'Export',
menu: Ext.create('Ext.menu.Menu', {
items: [
{
text: 'Export',
handler: function () {
var win = new innerWindow();
win.show();
}
}
]
})
});
It creates a dropdown that has a value called 'export'. I have managed to make it so that, when I click the 'Export', I get a window. For now this window is empty. What I have been looking for, and unable to find, is how to create a window that has some text inside, and some options (dropdown box), and labels etc.
More precisly, I want a window like the one I attached. I'm sure I can find examples on how to create this, but I just don't know what to search for. Searching on "Extjs window" and similar words, didnt bring me the help I'm looking for, nor looking at Senshas homepage (which normally has lots of brilliant examples).
Can someone help me out?
Thanks
In your code change
var win = new innerWindow();
to
var win = Ext.create('innerWindow');
Then just define your window with the form inside:
Ext.define('innerWindow', {
extend: 'Ext.window.Window',
title: 'title',
height: 200,
width: 500,
modal: true,
items: [{
xtype: 'form',
items: [{
xtype: 'textfield',
fieldLabel: 'Age',
name: 'age'
},{
xtype: 'textfield',
fieldLabel: 'Height',
name: 'height'
}],
fbar: [{
text: 'Submit',
formBind: true,
itemId: 'submit'
}]
}]
});
The documentation is here: form, textfield, combobox. Start reading the guides. You must read the docs to understand. ExtJs doc is well written.
Each ExtJS component has a property named items...
You should be adding the fields you want into the items property.
It would look something like this..
Ext.define('innerWindow', {
extend: 'Ext.window.Window',
title: 'title',
height: 200,
width: 500,
modal: true,
items:[
{
xtype:"textfield",
......
},{
xtype:"combobox",
store:myStore,
.......
}
]
});
You should check the docs of Window, it does have info about items, and it also does include examples.
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.window.Window
You should also include a layout for that window, for it to know how to arrange its items. Here's a link showing all types of layouts: http://dev.sencha.com/deploy/ext-4.0.0/examples/layout-browser/layout-browser.html
Also, I'm not sure about the new innerWindow, I'd rather use Ext.create('innerWindow') to create a new instance of a component you've defined.
Set Extjs Script
<script type='text/javascript' src='http://cdn.sencha.io/ext-4.2.0-gpl/ext-all.js'></script>
Set Extjs CSS
<link href="http://cdn.sencha.com/ext/gpl/4.2.0/resources/css/ext-all.css" rel="stylesheet"/>
Set Code
<script type='text/javascript'>
Ext.onReady(function() {
Ext.create('Ext.window.Window', {
title: 'Windows',
closable: true,
closeAction: 'hide',
width: 350,
minWidth: 250,
height: 125,
animCollapse:false,
border: false,
modal: true,
layout: {
type: 'border',
padding: 5
},
items: [{
xtype: 'form',
items: [{
xtype : 'combo',
fieldLabel : 'Age',
width : 320,
store : [ '18', '19', '20' ]
},{
xtype : 'combo',
fieldLabel : 'Height',
width : 320,
store : [ '1', '2', '3' ]
},],
fbar: [{
text: 'Submit',
formBind: true,
itemId: 'submit'
}]
}]
}).show();
});
</script>
Similar you want http://jsfiddle.net/ba3wnwpo/
I have a window on which I want to put 4 grids like this
Grid1 Grid2
Grid3 Grid4
and I want the grids to auto resize on window resize.
It is simple to do this with combined hbox/vbox layout like I did in the example above:
Ext.onReady(function () {
var me = this;
me.store = Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name', 'email', 'phone'],
data:{'items':[
{ 'name': 'Lisa', "email":"lisa#simpsons.com", "phone":"555-111-1224" }
]},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});
me.g1 = Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
flex: 1,
store: me.store,
columns: [
{ header: 'Name', dataIndex: 'name' },
{ header: 'Email', dataIndex: 'email', flex: 1 },
{ header: 'Phone', dataIndex: 'phone' }
]
})
//g2,g3,g4 same with g1
Ext.create('Ext.window.Window', {
title: 'Hello',
height: 400,
width: 600,
maximizable: true,
layout: 'fit',
items: [{
xtype: 'container',
layout: 'fit',
items: [{
xtype: 'container',
layout: {
type: 'vbox',
align: 'stretch'
},
items:[{
flex: 1,
xtype: 'container',
layout: 'hbox',
items:[me.g1, me.g2]
},{
flex: 1,
xtype: 'container',
layout: 'hbox',
items:[ me.g3, me.g4]
}]
}]
}]
}).show()
});
Everything works fine on chrome (the window opens in 1 sec), but on Internet Explorer, the window renders between 3-5 seconds, which is too much.
I also tried to float those 4 grids right and left and it rendered much better on IE, but that way I lose auto scroll on grids (unless I put each one in a fit container...) and when i click a record the grid goes up a number of pixels (~20px)
Any ideas on how to do this to work good on IE as well, without those 3-5 secs of rendering?
I am using ExtJs 4.0.7.
PS: The problem is not the loading of grid stores, they come on callback.
You definitely have more nesting than you need, which can significantly slow down the layout. Try getting rid of the 2 outer containers so it looks more like this:
Ext.create('Ext.window.Window', {
title: 'Hello',
height: 400,
width: 600,
maximizable: true,
layout: {
type: 'vbox',
align: 'stretch'
},
items:[{
flex: 1,
xtype: 'container',
layout: {
type: 'hbox',
align: 'stretch'
},
items:[me.g1, me.g2]
},{
flex: 1,
xtype: 'container',
layout: {
type: 'hbox',
align: 'stretch'
},
items:[me.g3, me.g4]
}]
}).show()
You might also consider initializing your window as hidden, then just show/hide it as you need it instead of re-creating it each time.
I am trying to populate a tabpanel with an extension I've created. Inside this extension i have a panel with 2 fields (timefield and datefield) which may have the values from my store.
Each of these fields may have different values in each tab. I am passing these values from the extended component via config. So far I can see these values in the console.log() but I can't put these values inside the fields.
This is how my extended component is:
Ext.define('PlaylistGrid', {
extend: 'Ext.panel.Panel',
alias: 'widget.playlistgrid',
border: false,
config: {
plIndex: 0,
plDate: '1970-10-10',
plTime: '00:00:00'
},
constructor: function(cfg) {
Ext.apply(this, cfg);
this.callParent(arguments);
},
items: [{
layout: 'hbox',
bodyStyle: 'padding: 5px',
border: false,
xtype: 'form',
name: 'myForm',
items: [{
xtype: 'datefield',
fieldLabel: 'Data de início',
name: 'datefld',
itemId: 'datefld'
}, {
xtype: 'timefield',
fieldLabel: 'Horário de início',
name: 'timefld'
}, {
xtype: 'button',
iconCls: 'save',
style: 'margin-left: 10px',
tooltip: 'Salvar data e hora',
handler: function() {
Ext.Msg.alert('Salvando...', 'Implementar');
}
}]
}, {
xtype: 'grid',
border: false,
width: '100%',
height: 476,
columns: [{
header: 'Ordem',
dataIndex: 'order',
width: 50
}, {
header: 'Video',
dataIndex: 'video',
width: 308
}, {
header: 'Duracao',
dataIndex: 'duration',
width: 100
}, {
header: 'Formato',
dataIndex: 'format',
width: 75
}]
}],
listeners: {
render: function(e, eOpts) {
console.log(e.getPlDate());
}
}
});
And this is how I am adding this component inside the tabpanel:
var plSt = Ext.getStore('playlistStore');
plSt.load();
plSt.on('load', function(store, records, successful, eOpts) {
plSt.each(function(record, idx) {
var playlist = {
xtype: 'playlistgrid',
title: 'Playlist ' + (records[idx].data.playlistId),
name: 'playlist' + idx,
plIndex: records[idx].data.playlistId,
plDate: records[idx].data.playlistDate,
plTime: records[idx].data.playlistTime
};
e.add(playlist);
});
if (records.length > 0) {
e.setActiveTab(1);
}
})
The data seems to be ok, but it does not display in the datefield... Do you have any point about it?
I have already search how to do this, but couldn't find the answer at all.
SOLVED
OK, I got it. The solution was simple. I just added a new config var that passes the current tab index, and the afterRender method.
I did this
afterRender: function(e, eOpts) {
var idx = e.getTabIdx();
var dateFld = Ext.ComponentQuery.query('datefield[name=datefld]');
dateFld[idx].setValue(new Date(e.getPlDate()));
//console.log(e.getPlDate());
}
Thank you!
I have this code
var main_container = Ext.create('Ext.container.Container',
{
xtype: 'container',
id: "id_container",
anchor: '100%',
layout:'column',
items:[
column_1,
column_2,
column_3
]
})
And when I resize the container the rightmost column in some cases disapears. When I resize again in some cases the rightmost column appears again. This happens only in IE.
What could be causing this? Any idea would be helpful.
Here is the structure of the rightmost column
var column_3 = Ext.create('Ext.container.Container',
{
columnWidth: .33,
layout: 'anchor',
id: 'column_3',
items:[
grid_1,
grid_2
]
})
There are 3 columns and i want them to be 33 percent wide
And the main container is oppened upon pressing ext js menu button.
And the main container is placed in ext js window.
This is my problem
<div class="x-container x-column x-container-default" id="column_roles" role="presentation" style="width: 400px;">
<DIV style="WIDTH: 413px; HEIGHT: 45%" id=grid_1 class="x-panel x-grid x-property-grid x-panel-default x-with-col-lines x-panel-with-col-lines x-panel-default-with-col-lines x-masked-relative x-masked" role=presentation aria-labelledby=component-1234>...</div>
<DIV style="WIDTH: 413px; HEIGHT: 45%" id=grid_2 class="x-panel x-grid x-property-grid x-panel-default x-with-col-lines x-panel-with-col-lines x-panel-default-with-col-lines x-masked-relative x-masked" role=presentation aria-labelledby=component-1237> ... </div>
</div>
you can see clearly that inner divs are wider than the one that contains them. Why IE generates badly? This doesnt happen in Chrome and FF.
If this happens only in IE, did you consider to discard IE as a browser? Jokes aside, if it works in any browser except IE maybe could be a bug or you have to do something special only for IE.
For example, this works for me:
Ext.onReady (function () {
Ext.create ('Ext.window.Window', {
renderTo: Ext.getBody () ,
title: 'Win' ,
width: 500 ,
height: 100 ,
layout: 'anchor' ,
resizable: true ,
items: [{
xtype: 'container' ,
anchor: '100%' ,
layout: 'column' ,
defaults: {
layout: 'anchor'
} ,
items: [{
xtype: 'container' ,
columnWidth: .33 ,
defaults: {
xtype: 'textfield' ,
anchor: '100%'
} ,
items: [{
fieldLabel: 'name'
} , {
fieldLabel: 'surname'
}]
} , {
xtype: 'container' ,
columnWidth: .33 ,
defaults: {
xtype: 'textfield' ,
anchor: '100%'
} ,
items: [{
fieldLabel: 'age'
} , {
fieldLabel: 'place'
}]
} , {
xtype: 'container' ,
columnWidth: .33 ,
defaults: {
xtype: 'textfield' ,
anchor: '100%'
} ,
items: [{
fieldLabel: 'nickname'
} , {
fieldLabel: 'whatever'
}]
}]
}]
}).show();
});
When you resize the window, each column is resized too and no one disappears.
Ciao
Wilk