-->

ComboBox showing HTML as text

2019-09-01 09:48发布

问题:

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);
    }
});

回答1:

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



回答2:

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