My treecolumn has a ComboBox as the editor component. The choices in the options menu are rendered correctly with HTML, but the input box does not render HTML, it only shows the tags (See images below.)
How I can make it to also render the value as HTML?
P.S.
This solution here EXTJS 4 render HTML of a selected value in a combobox is seems like not working with extjs6 version, check here
Here's the problem place code (rendere in case depth.TypeParameter: returns text with html tags)
{
xtype: 'treecolumn',
dataIndex: 'text',
text: Poly.utils.locale.Base.localeName,
flex: 1,
getEditor: function (record) {
return me.getController().getEditor(record);
},
renderer: function (value, meta, record) {
var depth = Poly.view.fluidProperties.sample.Tree.depth;
switch (record.getDepth()) {
case depth.Temperature:
if (Ext.isEmpty(record.get('temperature'))) {
return value;
}
var text = Ext.String.format('T = {0} {1}',
record.get('temperature').toFixed(2),
Poly.utils.UniSum.GetUnit(me.getViewModel().get('temperatureUnitId')).name);
return text;
case depth.TypeParameter:
if (record.get('isNew')) {
return value;
}
return Poly.enums.TypeFluidParameter.getName(record.get('fluidParameter'), record.parentNode.get('typeFluid'), true);
}
return value;
}
}
Full code here
Ext.define('Poly.view.fluidProperties.sample.Tree', {
extend: 'Ext.tree.Panel',
xtype: 'fluidPropertiesSampleTree',
viewModel: {
type: 'fluidPropertiesSampleTreeViewModel'
},
controller: 'fluidPropertiesSampleTreeController',
statics: {
/** Уровень элемента в дереве */
depth: {
/** Корень */
Root: 0,
/** Замер */
Sample: 1,
/** Тип среды */
TypeFluid: 2,
/** Параметер */
TypeParameter: 3,
/** Температура */
Temperature: 4
}
},
lines: false,
rootVisible: false,
useArrows: true,
enableColumnHide: false,
enableColumnResize: false,
sortableColumns: false,
border: true,
viewConfig: {
cls: 'gridActionColumnHide'
},
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
ui: 'footer',
cls: 'transparent',
layout: {
type: 'hbox',
align: 'middle',
pack: 'center'
},
items: [
{
xtype: 'button',
cls: 'pvt-chart-button',
text: '', // локализация в initComponent
flex: 2,
name: 'addSample',
margin: 2
},
{
xtype: 'button',
cls: 'pvt-chart-button',
text: '', // локализация в initComponent
flex: 1,
name: 'import',
disabled: true,
margin: 2
},
{
xtype: 'button',
cls: 'pvt-chart-button',
text: '', // локализация в initComponent
flex: 1,
name: 'export',
disabled: true,
margin: 2
}
]
}
],
listeners: {
checkchange: 'nodeCheckChange',
edit: 'edit'
},
plugins: {
ptype: 'cellediting',
clicksToEdit: 2
},
bind: {
selection: '{selectedRecord}'
},
initComponent: function () {
var me = this,
store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: []
}
}),
controller = me.getController();
me.dockedItems[0].items[0].text = me.locale.addSample;
me.dockedItems[0].items[1].text = me.locale.importText;
me.dockedItems[0].items[2].text = me.locale.exportText;
Ext.applyIf(me, {
store: store,
columns: [
{
xtype: 'treecolumn',
dataIndex: 'text',
text: Poly.utils.locale.Base.localeName,
flex: 1,
getEditor: function (record) {
return me.getController().getEditor(record);
},
renderer: function (value, meta, record) {
var depth = Poly.view.fluidProperties.sample.Tree.depth;
switch (record.getDepth()) {
case depth.Temperature:
if (Ext.isEmpty(record.get('temperature'))) {
return value;
}
var text = Ext.String.format('T = {0} {1}',
record.get('temperature').toFixed(2),
Poly.utils.UniSum.GetUnit(me.getViewModel().get('temperatureUnitId')).name);
return text;
case depth.TypeParameter:
if (record.get('isNew')) {
return value;
}
return Poly.enums.TypeFluidParameter.getName(record.get('fluidParameter'), record.parentNode.get('typeFluid'), true);
}
return value;
}
},
{
width: 30,
xtype: 'widgetcolumn',
name: 'menuWidgetcolumn',
widget: {
xtype: 'button',
margin: '5 0 0 0',
arrowCls: '',
width: 15,
height: 15,
style: {
'background-color': '000000',
'border-color': '000000'
},
menu: {
xtype: 'colormenu',
listeners: {
select: function (component, color) {
var button = component.up('button');
button.setStyle('background-color', color);
}
}
}
},
onWidgetAttach: function (column, widget, record) {
widget.setVisible(Ext.isNumber(record.get('temperature')));
}
},
{
xtype: 'actioncolumn',
width: 25,
items: [
{
handler: 'removeTreeItem',
getClass: function (v, meta, rec) {
if (!rec.get('isNew')) {
return 'poly-trash-icon';
}
return '';
},
getTip: function (v, meta, rec) {
if (!rec.get('isNew')) {
return 'Delete';
}
return '';
}
}
]
}
]
});
me.getSampleNode = controller.getSampleNode;
me.setTypeMode = Ext.bind(controller.setTypeMode, controller);
me.callParent(arguments);
}
});
Html input element can't display HTML, so you need to change template add div. Div can be shown as an overlay over input.
Best way to achieve this is by extending ComboBox:
Ext.define('HtmlComboBox', {
extend: 'Ext.form.field.ComboBox',
fieldSubTpl: [ // note: {id} here is really {inputId}, but {cmpId} is available
'<input id="{id}" data-ref="inputEl" type="{type}" {inputAttrTpl}',
' size="1"', // allows inputs to fully respect CSS widths across all browsers
'<tpl if="name"> name="{name}"</tpl>',
'<tpl if="value"> value="{[Ext.util.Format.htmlEncode(values.value)]}"</tpl>',
'<tpl if="placeholder"> placeholder="{placeholder}"</tpl>',
'{%if (values.maxLength !== undefined){%} maxlength="{maxLength}"{%}%}',
'<tpl if="readOnly"> readonly="readonly"</tpl>',
'<tpl if="disabled"> disabled="disabled"</tpl>',
'<tpl if="tabIdx != null"> tabindex="{tabIdx}"</tpl>',
'<tpl if="fieldStyle"> style="{fieldStyle}"</tpl>',
'<tpl foreach="inputElAriaAttributes"> {$}="{.}"</tpl>',
' class="{fieldCls} {typeCls} {typeCls}-{ui} {editableCls} {inputCls}" autocomplete="off"/>',
// overlay element to show formatted value
'<div id="{cmpId}-overlayEl" data-ref="overlayEl"<tpl if="name"> name="{name}-overlayEl"</tpl> class="{fieldCls}-overlay {typeCls} {typeCls}-{ui} {inputCls}">{value}</div>',
{
disableFormats: true
}
],
forceSelection: true,
childEls: [
'overlayEl'
],
setRawValue: function(value) {
var me = this;
// set value in overlay
if (me.rendered) {
me.overlayEl.update(value);
}
return me.callParent([value]);
}
});
With that, some additional CSS is required:
.x-form-text-wrap {
position: relative;
}
.x-form-field-overlay {
background-color: #ffffff;
position: absolute;
top: 0;
}
Fiddle: https://fiddle.sencha.com/#fiddle/14mm
I suppose that your editor is combo, by default combo (as well as many other components) display HTML as plain text.
Example
I guess as workaround you could overrite combo (or any other component), i.e. change component <input> element to <div>. It will entail overrites of some methods (setValue() for example).
Related
I have a grid with drag'n'drop and row editing plugins. It worked fined when it was an outer class. However, since I striped the grid from having a class and put as an inner component, it started giving me errors. If I comment out code concerning plugins, it works fine.
Ext.define('Dashboards.view.widgets.barChartAndLine.BarChartAndLineWidgetForm', {
extend: 'Dashboards.view.widgets.WidgetBaseForm',
xtype: 'barChartAndLineWidgetForm',
items : [{
xtype: 'grid',
rowEditing: null,
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop'
}
},
listeners: {
drop: function() {
this.updateData();
}
},
initComponent: function() {
var me = this;
this.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function() {
me.updateData();
}
}
});
this.plugins = [this.rowEditing];
this.callParent(arguments);
},
store: {
fields : ['label', 'linevalue', 'barvalue'],
bind : {
data : '{widget.data.data.items}'
}
},
columns: [{
header: 'Pavadinimas',
dataIndex: 'label',
flex: 3,
editor: {
allowBlank: false
}
}, {
xtype: 'numbercolumn',
header: 'Stulpelio reikšmė',
dataIndex: 'barvalue',
flex: 1,
editor: {
xtype: 'numberfield',
allowBlank: false
}
}, {
xtype: 'numbercolumn',
header: 'Linijos reikšmė',
dataIndex: 'linevalue',
flex: 1,
editor: {
xtype: 'numberfield',
allowBlank: false
}
}, {
xtype: 'actioncolumn',
width: 30,
items: [{
iconCls: 'x-fa fa-trash',
tooltip: 'Pašalinti',
handler: function(g, ri, ci) {
var grid = this.up().up();
grid.getStore().removeAt(ri);
grid.getStore().sync();
}
}]
}],
tbar: [{
xtype: 'button',
text: 'Pridėti',
handler: function() {
var grid = this.up().up();
var r = {
label: 'label',
linevalue: '0',
barvalue: '0'
};
var modelResult = grid.getStore().insert(0, r);
}
}]
}]
});
Instead of adding the rowediting plugin inside the initComponent function, you can set the plugin with grid's configs.
Based on your code have remote data, I created a fiddle to test the view, you can apply the view structure with your data.
If you have any question, let me know.
I try to show colorpicker in grid cell. But i can't do it correct. It must look like show/hide panel whith colorpiker and save piked color in grid cell.
I try to use several controls. But allways have problems. Please explain to do it right way.
Now it's look like this:
and the code:
{
xtype: "widgetcolumn",
dataIndex: "color",
text: "Color",
width: 60,
widget: {
xtype: 'colorpicker',
align: 'right',
value: '993300',
},
listeners: {
select: function(picker, selColor) {
value = selColor,
hide(this);
}
}
}
show color picker in grid cell.double click on grid row then select menu bar color and click on update plugin color show on grid row.code check in js fiddler
Ext.onReady(function () {
var userStore = Ext.create('Ext.data.Store', {
autoLoad: 'false',
fields: [
{ name: 'name' },
{ name: 'email' },
{ name: 'colorCode' }
],
data: [
{ name: 'Lisa', email: 'lisa#simpsons.com'},
{ name: 'Bart', email: 'bart#simpsons.com'},
{ name: 'Homer', email: 'homer#simpsons.com'},
{ name: 'Marge', email: 'marge#simpsons.com'},
{ name: 'Homer', email: 'homer#simpsons.com' },
{ name: 'Marge', email: 'marge#simpsons.com'},
]
});
var customColors = ['FF4848', 'FF7575', 'FFA8A8', 'FFBBBB', 'FFCECE', 'FFECEC', 'FF68DD', 'FF86E3', 'FFACEC', 'FFC8F2', 'FF62B0', 'FF73B9', 'FF86C2', 'FFA8D3',
'E469FE', 'EA8DFE', 'EFA9FE', 'D568FD', 'D97BFD', 'DD88FD', 'E7A9FE', '9669FE', 'A27AFE', 'C4ABFE', 'D0BCFE', 'DDCEFF', 'FFA4FF', 'EAA6EA', 'D698FE', 'CEA8F4',
'BCB4F3', 'A9C5EB', '8CD1E6', 'FFBBFF', 'EEBBEE', 'DFB0FF', 'DBBFF7', 'CBC5F5', 'BAD0EF', 'A5DBEB', 'FFCEFF', 'F0C4F0', 'E8C6FF', 'E1CAF9', 'D7D1F8', 'CEDEF4',
'B8E2EF', '62A9FF', '62D0FF', '06DCFB', '01FCEF', '03EBA6', '01F33E', '99E0FF', '63E9FC', '74FEF8', '62FDCE', '72FE95', 'C0F7FE', 'CEFFFD', 'BEFEEB', 'CAFFD8',
'1FCB4A', '59955C', '48FB0D', '2DC800', '59DF00', '9D9D00', 'B6BA18', 'DFDF00', 'DFE32D', '93EEAA', 'A6CAA9', 'AAFD8E', '6FFF44', 'ABFF73', 'FFFF84', 'E7F3F1',
'EEF093', 'BDF4CB', 'C9DECB', 'CAFEB8', 'A5FF8A', 'D1FFB3', 'FFFFB5', 'F5F7C4', 'BABA21', 'C8B400', 'DFA800', 'DB9900', 'FFB428', 'FF9331', 'FF800D', 'D8F0F8',
'E6E671', 'E6CE00', 'FFCB2F', 'FFB60B', 'FFC65B', 'FFAB60', 'FFAC62', 'F7DE00', 'FFD34F', 'FFBE28', 'FFCE73', 'FFBB7D', 'FFBD82', 'EEEECE', 'EADFBF', 'E4C6A7',
'E6C5B9', 'DEB19E', 'E8CCBF', 'DDB9B9', 'E1E1A8', 'DECF9C', 'DAAF85', 'DAA794', 'CF8D72', 'DAAC96', 'D1A0A0', 'FF8E8E', 'E994AB', 'FF7DFF', 'D881ED', 'B7B7FF',
'A6DEEE', 'CFE7E2', 'FFC8C8', 'F4CAD6', 'FFA8FF', 'EFCDF8', 'C6C6FF', 'C0E7F3', 'DCEDEA', 'FFEAEA', 'F8DAE2', 'FFC4FF', 'EFCDF8', 'DBDBFF'];
Ext.create('Ext.window.Window', {
height: 400,
width: 350,
xtype: 'panel',
layout: 'fit',
items:
[
{
layout: 'border',
height: 200,
renderTo: Ext.getBody(),
items:
[
{
xtype: 'grid',
// height: 300,
region: 'center',
id: 'GridId',
store: userStore,
columns: [
{
header: 'Name',
width: 100,
sortable: false,
hideable: false,
dataIndex: 'name',
editor: {
xtype: 'textfield'
}
},
{
header: 'Email Address',
width: 150,
dataIndex: 'email',
editor: {
xtype: 'textfield',
}
},
{
header: 'Color',
dataIndex: 'colorCode',
width: '20%',
renderer: function (value, metaData) {
metaData.tdAttr = 'bgcolor=' + value;
return value;
},
editor: {
xtype: 'button',
text: 'Color Menu',
menu: new Ext.menu.ColorPicker({
resizable: true,
scrollable: true,
listeners: {
select: function (metaData, value) {
metaData.up('grid').getSelection()[0].dirty = true;
metaData.up('grid').getSelectionModel().getSelection()[0].data.colorCode = value;
}
}
}),
listeners: {
render: function (metaData, value) {
metaData.down('colorpicker').colors = [];
metaData.down('colorpicker').value = metaData.ownerCt.context.grid.getSelectionModel().getSelection()[0].data.colorCode;
for (var i = 0; i < customColors.length; i++) {
metaData.down('colorpicker').colors.push(customColors[i]);
}
metaData.down('colorpicker').updateLayout();
}
}
}
},
],
selModel: 'rowmodel',
plugins: {
ptype: 'rowediting',
clicksToEdit: 2
},
}
]
}]
}).show();
});
I have a gridpanel with a subtable inside every row. Im trying to include a double click functionality (if you click 2 times in a row, obtain the id_amenaza and redirent with an url). The code works but if i make double click collapses the row. How can i add this functionality? (or insert an image that acts as a link?)
//GRIDPANEL
Ext.create('Ext.grid.Panel', {
renderTo: 'example-grid',
store: amenazaStore,
width: 748,
height: 598,
title: '<bean:write name="informesAGRForm" property="nombreActivo"/>',
plugins: [{
ptype: "subtable",
headerWidth: 24,
listeners: {
'rowdblclick': function(grid, rowIndex, columnIndex, e){
// Get the Record, this is the point at which rowIndex references a
// record's index in the grid's store.
var record = grid.getStore().getAt(rowIndex);
// Get field name
var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
var data = record.get(fieldName);
alert(data);
}
},
columns: [{
text: 'id_amenaza',
dataIndex: 'id_amenaza',
hidden: true,
width: 100
}, {
width: 100,
text: 'id_salvaguarda',
dataIndex: 'id_salvaguarda'
},
{
text: 'denominacion',
dataIndex: 'denominacion',
width: 100
},{
text: 'descripcion',
dataIndex: 'descripcion',
width: 100
},{
text: 'eficacia',
dataIndex: 'eficacia',
width: 100
},
],
getAssociatedRecords: function (record) {
var result = Ext.Array.filter(
salvaguardaStore.data.items,
function (r) {
return r.get('id_amenaza') == record.get('id');
});
return result;
}
}],
collapsible: false,
animCollapse: false,
columns: [
{
text: 'ID',
hidden: true,
hideable: false,
dataIndex: 'id'
},
{
text: 'Codigo',
width: 50,
sortable: true,
hideable: false,
dataIndex: 'codigo'
},
{
text: 'Denominación',
width: 150,
dataIndex: 'denominacion',
},
{
text: ' Autenticidad',
flex: 1,
dataIndex: 'a_riesgo'
},
{
text: 'Confidencialidad',
flex: 1,
dataIndex: 'c_riesgo'
},
{
text: 'Integridad',
flex: 1,
dataIndex: 'i_riesgo'
},
{
text: 'Disponibilidad',
flex: 1,
dataIndex: 'd_riesgo'
},
{
text: 'Trazabilidad',
flex: 1,
dataIndex: 't_riesgo'
},
{
text: 'Total',
flex: 1,
dataIndex: 'total_riesgo'
}]
});
}
Thank you in advance.
First of all you must attach rowdblclick to main grid. To detect which subtable row was clicked you must use event object.
Example:
'rowdblclick': function (view, record, tr, columnIndex, e) {
var cell = e.getTarget('.x-grid-subtable-cell');
if (!cell) {
return;
}
var row = Ext.get(cell).up('tr');
var tbody = row.up('tbody');
var rowIdx = tbody.query('tr', true).indexOf(row.dom);
var records = view.up('grid').getPlugin('subtable').getAssociatedRecords(record);
var subRecord = records[rowIdx];
console.log(subRecord);
}
To turn off expanding/collapsing set expandOnDblClick: false on plugin.
Working sample: http://jsfiddle.net/7czs02yz/18/
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'm creating a simple SCRUM system in order to teach myself to use EXT 4, so it goes without saying that I'm very new to the framework.
I have a little experience with MVC3 but I'm having some trouble adapting to the way EXT4 works.
My idea is to have 4 grids in a column layout Viewport. Each of the grids is currently its own View. However the Views are almost completely identical. Below is my first View. I've marked the lines that I have to change for the other 3 views.
Ext.define('AM.view.card.BacklogList', { // *** Variable
extend: 'Ext.grid.Panel',
alias: 'widget.backlogcardlist', // *** Variable
title: 'Backlog', // *** Variable
store: 'BacklogCards', // *** Variable
selType: 'cellmodel',
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
columns: [
{
header: 'ID',
dataIndex: 'external_id',
field: 'textfield',
width: 50
},
{
header: 'Name',
dataIndex: 'name',
field: 'textfield',
width: 200
},
{
header: 'Priority',
dataIndex: 'priority_id',
renderer: function (value) {
if (value == 3) {
return "L";
}
else if (value == 2) {
return "M";
}
else {
return "H";
}
},
width: 70,
field: {
xtype: 'combobox',
queryMode: 'local',
typeAhead: true,
store: 'Priorities',
displayField: 'name',
valueField: 'id',
listClass: 'x-combo-list-small'
}
},
{
xtype: 'actioncolumn',
width: 16,
items: [{
icon: 'Styles/Images/zoom.png', // Use a URL in the icon config
tooltip: 'Zoom In',
handler: function (grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
alert("Edit " + rec.get('name'));
}
}]
}
]
});
Is there a way in EXTjs to pass a 'ViewModel'/Parameters to my View so that I can re-use it for each of my grids?
app.js
Ext.application({
name: 'AM',
appFolder: 'app',
controllers: ['BacklogCards', 'InprogressCards', 'ReviewCards', 'DoneCards'],
launch: function () {
Ext.create('Ext.container.Viewport', {
layout: 'column',
items: [
{
xtype: 'backlogcardlist'
},
{
xtype: 'inprogresslist'
},
{
xtype: 'reviewlist'
},
{
xtype: 'donelist'
}
]
});
}
});
Ok! I figured it out by reading this post here:
Extjs 4 MVC loading a view from controller
This is how I modified my app.js file:
Ext.application({
name: 'AM',
appFolder: 'app',
controllers: ['BacklogCards', 'InprogressCards', 'ReviewCards', 'DoneCards'],
launch: function () {
Ext.create('Ext.container.Viewport', {
layout: 'column',
defaults: { flex: 1 },
layout: {
type: 'hbox',
align: 'stretch',
padding: 5
},
items: [
Ext.widget('backlogcardlist',
{
title: "Backlog"
}),
Ext.widget('backlogcardlist',
{
title: "In Progress"
}),
{
xtype: 'reviewlist'
},
{
xtype: 'donelist'
}
]
});
}
});
Here I'm just changing the title property, but I imagine changing the other properties shouldn't be anymore difficult.