ExtJS Advanced Fluid Border Layout - layout

I need to create an advanced, fluid Border layout for our Report system.
The West pane would be split into 2 separate panes, top for the filter form, and the bottom for navigation.
The Center pane would be split into 3 separate panes, top for the primary data grid, and 2 bottom panes for sub report grids. I may at some point need 3 bottom panes, but I'm hoping to avoid that.
Here is an example of what I am looking for: http://dl.dropbox.com/u/298258/Amistaff/desiredLayout.png
What I have so far is definitely less than satisfactory.
http://dl.dropbox.com/u/298258/Amistaff/currentLayout.png
Here is the code:
var ReportForm = new Ext.FormPanel({
url: '',
frame: false,
border: false,
title: 'Filter Results',
width: 260,
labelWidth: 50,
padding: '10 0 0 5',
standardSubmit: true,
items: [
{
fieldLabel: 'Client',
hiddenName: 'ClientID',
mode: 'local',
store: frmClientStore,
displayField: 'CompanyName',
valueField: 'ClientID',
width: 150,
editable: true,
triggerAction: 'all',
xtype: 'combo'
}
],
buttons: [
{text:'Export',handler:function(){}},
{text:'Search',handler:function(){}},
{text:'Reset',handler:function(){}}
]
});
var ReportGrid = new Ext.grid.GridPanel({
id: 'ReportGrid',
width: '100%',
height: '50%',
viewConfig: {
forceFit: true
},
autoHeight: true,
loadMask: true,
stripeRows: true,
store: ReportStore,
margins: '5 5 5 5',
cm: ReportColumnModel
,bbar: new Ext.PagingToolbar
(
{
pageSize: 10,
store: ReportStore,
displayInfo: true,
displayMsg: 'Displaying results {0} - {1} of {2}'
}
)
});
var viewport = new Ext.Viewport({
layout: 'border',
items: [
{
region: 'west',
layout: 'vbox',
layoutConfig: {
align: 'stretch'
},
width: 260,
minSize: 175,
maxSize: 400,
margins: '5 5 5 5',
items: [
ReportForm,
{
region: 'south',
title: 'Superuser',
border: false,
xtype: 'tabpanel',
activeTab: 0,
items: [
{
title: 'General',
xtype: 'panel',
height: 200,
html: '',
},
{
title: 'Exams',
height: 200,
html: ''
}
]
}
]
},
new Ext.Panel({
region: 'center',
deferredRender: false,
layout: 'fit',
margins: '5 5 5 0',
items: [
ReportGrid,
new Ext.Panel({
region: 'south',
border: false,
height: '50%',
html: 'foo',
layout: 'fit',
items: [
new Ext.Panel({
region: 'west',
width: '50%',
border: false,
html: 'West'
}),
new Ext.Panel({
region: 'east',
width: '50%',
border: false,
html: 'East'
})
]
})
]
})
]
});
Thanks...
EDIT:
Many thanks to amol for the answer below. I have one additional question. If I collapse the form in the west region, how do I make it resize the navigation panel to fill the remaining space?

code -
var ReportForm = new Ext.FormPanel({
url: '',
frame: false,
border: false,
title: 'Filter Results',
width: 260,
labelWidth: 50,
padding: '10 0 0 5',
standardSubmit: true,
items: [
{
fieldLabel: 'Client',
hiddenName: 'ClientID',
mode: 'local',
//store: frmClientStore,
displayField: 'CompanyName',
valueField: 'ClientID',
width: 150,
editable: true,
triggerAction: 'all',
xtype: 'combo'
}
],
buttons: [
{text:'Export',handler:function(){}},
{text:'Search',handler:function(){}},
{text:'Reset',handler:function(){}}
]
});
var ReportGrid = new Ext.grid.GridPanel({
id: 'ReportGrid',
flex:1,
viewConfig: {
forceFit: true
},
loadMask: true,
stripeRows: true,
//store: ReportStore,
margins: '5 5 5 5',
cm: new Ext.grid.ColumnModel({
columns:[
{header:'A column', dataIndex:'afield'},
{header:'B column', dataIndex:'bfield'}
]
}),
store:new Ext.data.ArrayStore({
autoLoad:true,
fields:['afield', 'bfield'],
data:[['value 1','value 3'],['value 2', 'value4']]
}),
bbar: new Ext.PagingToolbar
(
{
pageSize: 10,
//store: ReportStore,
displayInfo: true,
displayMsg: 'Displaying results {0} - {1} of {2}'
}
)
});
var viewport = new Ext.Viewport({
layout: 'border',
items: [
{
region: 'west',
layout: 'vbox',
layoutConfig: {
align: 'stretch'
},
width: 260,
minSize: 175,
maxSize: 400,
margins: '5 5 5 5',
items: [
ReportForm,
{
region: 'south',
title: 'Superuser',
border: false,
xtype: 'tabpanel',
activeTab: 0,
items: [
{
title: 'General',
xtype: 'panel',
height: 200,
html: ''
},
{
title: 'Exams',
height: 200,
html: ''
}
]
}
]
},
new Ext.Panel({
region: 'center',
deferredRender: false,
layout: 'vbox',
layoutConfig:{align:'stretch'},
margins: '5 5 5 0',
items: [
ReportGrid,
{
border: false,
flex:1,
layout: 'hbox',
layoutConfig:{align:'stretch'},
defaults:{flex:1},
items: [
new Ext.Panel({
html: 'West'
}),
new Ext.Panel({
html: 'East'
})
]
}
]
})
]
});

Related

JointJS how to create a HTML select (drop down) inside a shape object

I am looking for best practises or advice in how to create interactive elements within Shapes (elements) using the JointJS (Rappid) library.
This is what I have done currently:
The code
const shape = new joint.shapes.basic.Generic({
type: 'shape',
attrs: {},
markup: [
{
tagName: 'foreignObject',
selector: 'foreignObject',
attributes: {
x: '10',
y: '10',
width: '60',
height: '100',
},
children: [
{
tagName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
selector: 'content',
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
children: [
{
tagName: 'select',
selector: 'select',
style: {
'z-index': 1,
},
children: [
{
tagName: 'option',
value: 'test1',
textContent: 'test 1',
},
{
tagName: 'option',
value: 'test2',
textContent: 'test 2',
},
],
},
],
},
],
},
],
});
You can see there is a shape rendered and it has a select element in it by using a foreignObject (https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject).
However, using foreignObject is troublesome due to that they do not play well in browsers and the drop down you see here doesn't actually work.
I could start hacking around and get it to work but this is the point of the question, is there a cleaner way in achieving this?
I need something like this
https://resources.jointjs.com/tutorial/html-elements
But the html library is now decrepitated and JointJS wants you to use markup JSON instead.
Lastly, I have seen this post which doesn't fill me much with confidence...
https://groups.google.com/g/jointjs/c/-yXXlnreq6M
But I am hoping as this is from 5 years ago, it is outdated and we don't need to have to do the workarounds as it suggests?
HTML can be added inside foreignObject, but as you mentioned there can be some issues in browsers. One example of using foreignObject can be found here.
The code demonstrates how to create a text input with foreignObject.
var paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 650,
height: 400,
gridSize: 10,
model: graph,
guard: function(evt) {
return evt.target instanceof HTMLInputElement;
}
});
paper.on('blank:pointerdown cell:pointerdown', function() {
document.activeElement.blur();
});
var Example = joint.dia.Element.define('example.ForeignObject', {
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
stroke: '#333333',
fill: '#ffffff',
strokeWidth: 2
},
foreignObject: {
refWidth: '100%',
refHeight: '100%'
}
}
}, {
markup: [{
tagName: 'rect',
selector: 'body'
}, {
tagName: 'foreignObject',
selector: 'foreignObject',
attributes: {
'overflow': 'hidden'
},
children: [{
tagName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
selector: 'content',
style: {
fontSize: 14,
width: '100%',
height: '100%',
position: 'static',
backgroundColor: 'transparent',
textAlign: 'center',
margin: 0,
padding: '0px 10px',
boxSizing: 'border-box',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
},
children: [{
tagName: 'span',
textContent: 'First Name'
}, {
tagName: 'input',
selector: 'firstname',
attributes: {
'type': 'input',
'name': 'firstname'
},
style: {
position: 'static',
width: '100%'
}
}, {
tagName: 'span',
textContent: 'Last Name'
}, {
tagName: 'input',
selector: 'lastname',
attributes: {
'type': 'input',
'name': 'lastname'
},
style: {
position: 'static',
width: '100%'
}
}]
}]
}]
}, {
attributes: {
value: {
set: function(text, _, node) {
if ('value' in node) node.value = text;
}
}
}
});
joint.shapes.example.ForeignObjectView = joint.dia.ElementView.extend({
events: {
'change input': 'onInputChange'
},
onInputChange: function(evt) {
var input = evt.target;
this.model.attr(input.name + '/value', input.value);
}
});
The article that you linked is deprecated, but there is an updated version of creating elements with a HTML face here. You can see some select fields demonstrated there, but it is a little more involved.

High Charts export-server not rending legend LabelFormatter

I have the following code for the node.js high-Charts export-server the legend is showing but the label formatted is not applied and the function is not executed also
I have tried the load function also and it is not working, I tried custom HTML and it is now showing also
let chartDetails = {
type: "png",
options: {
chart: {
type: "pie",
showInLegend: true,
dataLabels: {
enabled: false
}
},
title: {
align: 'left',
floating: false,
text: 'Main Title',
style: {
fontSize: '24px'
}
},
subtitle: {
verticalAlign: 'middle',
align: 'center',
floating: false,
text: '<b>300</b><br>Total Issues',
style: {
fontSize: '30px'
}
},
plotOptions: {
pie: {
innerSize: '70%',
shadow: false,
showInLegend: true,
dataLabels: {
enabled: false,
}
}
},
legend: {
enabled: true,
floating: true,
borderWidth: 0,
align: 'right',
layout: 'vertical',
verticalAlign: 'middle',
useHTML: true,
labelFormatter: function () {
console.log("this: is equal to ");
console.log(this);
return 'custom word';
}
}
,
series: [
{
data: [
{
name: "a",
y: 100
},
{
name: "b",
y: 20
},
{
name: "c",
y: 50
}
]
}
]
}
};
I expected 'custom word' instead 'a','b','c' is showing
It seems when using node-export-server as a module callback functions are not supported. Check this thread on the module github: https://github.com/highcharts/node-export-server/issues/122.
As a workaround, you can use labelFormat property instead of labelFormatter:
legend: {
enabled: true,
floating: true,
borderWidth: 0,
align: 'right',
layout: 'vertical',
verticalAlign: 'middle',
useHTML: true,
labelFormat: "custom word"
}

Aligning labels in highchart donut

I'm trying to make a highchart donut with a legend on the side,
I'm really struggling to get the data labels to be more centered. At the moment each of them are in a different place,
an image of intended result:
https://codepen.io/mattdavidson/pen/qgqZyV
Highcharts.chart('container', {
credits: { enabled: false },
chart: { height: 300, width: 500, animation: false },
title: {
align: 'center',
verticalAlign: 'middle',
text: 10,
y: 25,
x: 55,
style: { color: '#333333', fontSize: '72px', fontWeight:'bold'},
},
plotOptions: {
pie: {
dataLabels: {
enabled: true,
format: '{point.y}',
distance: -25,
style: { fontSize: '32px', textOutline: 0 },
},
animation: false,
showInLegend: true,
},
},
legend: {
layout: 'vertical',
verticalAlign: 'middle',
align: 'left',
symbolHeight: 25,
symbolRadius: 5,
itemMarginTop: 10,
itemMarginBottom: 10,
},
series: [
{
type: 'pie',
innerSize: '55%',
colors: ['rgb(212,33,71)', 'rgb(250,189,43)', 'rgb(60,168,74)'],
data: [['Category 1', 4], ['Category 2', 5], ['Category 3', 1]],
},
],
});
There is an issue reported on Highcharts github about donut labels position. Check it here: https://github.com/highcharts/highcharts/issues/9005.
I've changed some options and added custom text using Highcharts.SVGRenderer#text (dynamic sum of all values) on the donut center. Perhaps it will help you: https://jsfiddle.net/BlackLabel/2jmqext9/.
Code:
Highcharts.chart('container', {
credits: {
enabled: false
},
chart: {
height: 300,
width: 500,
animation: false,
events: {
load: function() {
var chart = this,
offsetLeft = -20,
offsetTop = 10,
x = chart.plotLeft + chart.plotWidth / 2 + offsetLeft,
y = chart.plotTop + chart.plotHeight / 2 + offsetTop,
value = 0;
chart.series[0].yData.forEach(function(point) {
value += point;
});
chart.renderer.text(value, x, y).add().css({
fontSize: '30px'
}).toFront();
}
}
},
plotOptions: {
pie: {
dataLabels: {
enabled: true,
color: '#fff',
format: '{point.y}',
distance: -25,
style: {
fontSize: '20px',
textOutline: 0
},
},
animation: false,
showInLegend: true,
},
},
legend: {
layout: 'vertical',
verticalAlign: 'middle',
align: 'left',
symbolHeight: 15,
symbolRadius: 5,
symbolPadding: 10,
itemMarginTop: 10,
itemMarginBottom: 10,
itemStyle: {
fontSize: '15px'
}
},
series: [{
type: 'pie',
innerSize: '55%',
colors: ['rgb(212,33,71)', 'rgb(250,189,43)', 'rgb(60,168,74)'],
data: [
['Category 1', 4],
['Category 2', 2],
['Category 3', 12]
],
}, ],
});

Extjs child item not filling the parent container

My problem is, even if I used "layout: 'fit'" in all my children items within a boarder layout, they just shrinks into a small box rather than fill the parent, as described in fit layout.
I want the EDS.view.selector.Container to fill the "navigation" section of my boarder layout.
(Code excerpt)
Ext.define('EDS.view.selector.Container', {
extend: 'Ext.panel.Panel',
alias : 'widget.selectorcontainer',
layout: 'fit',
initComponent: function(){
this.items = [
{
xtype: 'tabpanel',
defaults: {
bodyPadding: 10
},
layout: 'fit',
items:[
{
title: 'Organization',
id: 'selector-organization',
tag: 'div',
html: 'div here',
height: '100%',
}
]
}
],
this.callParent();
},
});
(Controller)
init: function(){
console.log('controller.init()');
new Ext.Viewport({
title: 'Data Analysis',
layout: 'border',
defaults: {
collapsible: true,
split: true,
bodyStyle: 'padding: 15px',
},
items: [{
title: 'Navigation',
region:'west',
margins: '5 0 0 0',
cmargins: '5 5 0 0',
width: 600,
minSize: 100,
maxSize: 250,
items: [
{
id: 'selector-container',
xtype: 'selectorcontainer',
layout: 'fit',
}
]
},{
title: 'Main Content',
collapsible: false,
region:'center',
margins: '5 0 0 0'
}]
});
}
You did not set up layout for wrapper containers in your border layout:
items: [{
title: 'Navigation',
region:'west',
layout: 'fit',
...
items: [
]
},{
title: 'Main Content',
collapsible: false,
region:'center',
layout: 'fit',
...
}]
Remember: In ExtJS any plain JS object that goes into items property of a container will be converted into some type of Ext component with xtype defined by defaultType property of that container. In most cases it will be panel.

problem with extjs fields layout

i have the problem with displaying fields on form
var test = Ext.create('Ext.form.Panel', {
renderTo: 'test',
title: '1. zzzz',
width: 800,
bodyPadding: 5,
defaults: {
anchor: '100%'
},
items: [
{
xtype: 'fieldset',
defaults: {
anchor: '100%'
},
layout: 'column',
items: [
{
xtype: 'panel',
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
columnWidth: .5,
flex: 1,
defaultType: 'textfield',
defaults: {
anchor: '100%',
flex: 1
},
items: [
{
xtype: 'numberfield',
hideTrigger: true,
fieldLabel: 'zzzz',
//anchor: '100%',
//anchor: '-5',
name: 'SRD_NUMBER'
},
{
fieldLabel: 'zzzz',
//anchor: '-5',
name: 'SRD_NAME_BR'
},
{
fieldLabel: 'zzzzz',
//anchor: '-5',
name: 'SRD_NAME_FL'
},
{
xtype: 'numberfield',
hideTrigger: true,
fieldLabel: 'zzzz',
disabled: true,
//anchor: '-5',
name: 'SRD_FOP'
},
{
fieldLabel: 'zzzz',
//anchor: '-5',
name: 'SRD_NAME_ORDER'
},
{
xtype: 'panel',
id: 'dep-img',
border: false,
height: 50,
width: 100,
cls: 'x-form-item',
html: '<img src="http://dep-image/id/10000001482" width="100" height="50" title="zzz">'
},
{
xtype: 'filefield',
name: 'file1',
msgTarget: 'side',
border: 3,
//anchor: '100%',
fieldLabel: 'zzzz',
buttonText: 'zzzzzz'
},
{
fieldLabel: 'zzz',
//anchor: '-5',
name: 'company'
},
{
fieldLabel: 'zzzz',
//anchor: '-5',
name: 'company'
}]
}
]
} //fieldset
]//glob
});
i need to fit fields width to column width.
on this page http://docs.sencha.com/ext-js/4-0/#/api/Ext.form.FieldContainer 2 examples
and in second example they set defaults {layout: '100%'} and it looks like it does not work.
found own salvation: by adding layout: 'fit' or layout: 'anchor' to fieldset anchor
defaults: {
layout: 'fit',
flex: 1
},
thanks to all
You must set height property to your form and if it still is not displaying then give height to fieldset too.
found own salvation: by adding layout: 'fit' or layout: 'anchor' to fieldset anchor
defaults: {
layout: 'fit',
flex: 1
},
thanks to all
I would specify layout:'fit' on the formPanel since you are using a single fieldset.
The rest i dont understand. It looks like you specify column layout but using just one column.
Could you clean up the example and i would be happy to help.
After a quick look... Have you tried putting anchor: '0' on both fields and containers?
Also, you should use fieldDefaults instead of
defaults: {
anchor: '100%',
flex: 1
},

Resources