0

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

First step

Second step

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);
    }
});
Community
  • 1
  • 1
DanilGholtsman
  • 2,354
  • 4
  • 38
  • 69

2 Answers2

3

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

Krzysztof
  • 15,900
  • 2
  • 46
  • 76
  • wow, thanks so much! How did you get what to do here? Is there some additional info about how to work with tpls in extjs? – DanilGholtsman Jan 27 '16 at 11:13
  • You have source available, that's the best info you can get. – Krzysztof Jan 27 '16 at 11:28
  • hmm, thx, found problem here - blur event seems worked but not changed anything – DanilGholtsman Jan 28 '16 at 10:34
  • i guess it's because it need to be working with focus and blur classes! haha – DanilGholtsman Jan 28 '16 at 11:18
  • 1
    You asked how to do it, I showed you how, but it doen't mean you can paste it and it will work straightaway. – Krzysztof Jan 28 '16 at 12:57
  • I thought that it will inherit all this stuff from his parent, `ComboBox`. I used it as editor for `treecolumn` component – DanilGholtsman Jan 28 '16 at 13:15
  • 1
    I've changed template, and now it should behaves a bit better. Instead of replacing input with div, I added div overlay. – Krzysztof Jan 29 '16 at 06:13
  • thanks, but, well, got such http://i.imgur.com/wTkpGZZ.png problem here. Tried to make own css class with `display: none !important` and use id inside `` in `fieldSubTpl` but then events (focus/collapse) screwed. – DanilGholtsman Feb 03 '16 at 05:46
  • Finally make it looks okay! Thanks again, mr.Krzysztof! Just edit the answer pls, like that in css `.x-form-required-field-overlay { background-color: #ffffff; position: absolute; top: 0; left: 0; }` – DanilGholtsman Feb 03 '16 at 12:05
1

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).

Sergey Novikov
  • 4,096
  • 7
  • 33
  • 59