Magento 2.1 Ui Component field field Entrada de token

16

Quiero agregar etiquetas en un campo de entrada, de una manera similar a como se hace en forma de producto para agregar catageories, que se muestra en la imagen a continuación. ingrese la descripción de la imagen aquí

Esta tarea la he logrado agregando un componente de campo en el formulario Ui personalizado

<field name="parent">
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="object">Magento\Catalog\Ui\Component\Product\Form\Categories\Options</item>
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Tags</item>
                <item name="componentType" xsi:type="string">field</item>
                <item name="formElement" xsi:type="string">select</item>
                <item name="component" xsi:type="string">Magento_Catalog/js/components/new-category</item>
                <item name="elementTmpl" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                <item name="dataScope" xsi:type="string">data.parent</item>
                <item name="filterOptions" xsi:type="boolean">true</item>
                <item name="showCheckbox" xsi:type="boolean">false</item>
                <item name="disableLabel" xsi:type="boolean">true</item>
                <item name="multiple" xsi:type="boolean">true</item>
                <item name="levelsVisibility" xsi:type="number">1</item>
                <item name="sortOrder" xsi:type="number">20</item>
                <item name="required" xsi:type="boolean">true</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item>
                </item>
                <item name="listens" xsi:type="array">
                    <item name="${ $.namespace }.${ $.namespace }:responseData" xsi:type="string">setParsed</item>
                </item>
            </item>
        </argument>
    </field>

Pero esto no cumple con mi requisito. No necesito el menú desplegable y las opciones: solo quería agregar las etiquetas en el campo de entrada, como Etiqueta1, Etiqueta2, Etiqueta 3 ... ¿Puede alguien guiarme donde podamos hacer los posibles cambios para lograr esta tarea?

Verdu
fuente

Respuestas:

1

La respuesta rápida es , todo es posible con UI Components porque es realmente flexible como sus introducciones.

De lo contrario, no creo que depender / anular el elemento de IU predeterminado (como mencionaste en la publicación ui-select) sea una buena idea. Entonces, en este tutorial, crearé un nuevo elemento de interfaz de usuario para las etiquetas. Podría usarse no solo en forma de producto sino también en la página de cms o lo que sea que dependa de los formularios de la interfaz de usuario.

¡Ahora que comience la diversión!

En primer lugar, su formulario ui_component debería verse así

StackOverflow / Catalog / view / adminhtml / ui_component / product_form.xml

<field name="parent">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Tags</item>
            <item name="componentType" xsi:type="string">field</item>
            <item name="formElement" xsi:type="string">input</item>
            <item name="component" xsi:type="string">StackOverflow_Catalog/js/form/element/tags</item>
            <item name="elementTmpl" xsi:type="string">StackOverflow_Catalog/form/element/tags</item>
            <item name="dataScope" xsi:type="string">data.parent</item>
            <item name="filterOptions" xsi:type="boolean">true</item>
            <item name="showCheckbox" xsi:type="boolean">false</item>
            <item name="disableLabel" xsi:type="boolean">true</item>
            <item name="levelsVisibility" xsi:type="number">1</item>
            <item name="sortOrder" xsi:type="number">20</item>
            <item name="required" xsi:type="boolean">true</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
            <item name="listens" xsi:type="array">
                <item name="${ $.namespace }.${ $.namespace }:responseData" xsi:type="string">setParsed</item>
            </item>
        </item>
    </argument>
</field>

Tome una nota para formElement , component y elementTmpl . Debería ser un campo de entrada normal.

Ahora, necesitamos crear el renderizador de vistas para ese elemento de la interfaz de usuario

StackOverflow / Catalog / view / base / web / js / form / element / tags.js

/**
 * StackOverflow Catalog.
 *
 * @category  Mage
 *
 * @author    Toan Nguyen <[email protected]>
 * @copyright 2018 Toan Nguyen (https://nntoan.com)
 */
define([
    'underscore',
    'mageUtils',
    'Magento_Ui/js/form/element/abstract',
    'ko',
    'Magento_Ui/js/lib/validation/validator'
], function (_, utils, Element, ko, validator) {
    'use strict';

    return Element.extend({
        defaults: {
            list: ([]),
            valueUpdate: 'afterkeydown',
            listens: {
                'valueArea': 'onUpdateArea'
            }
        },

        initialize: function () {
            this._super();
            this.on('value', this.onUpdateArea.bind(this));
            var self = this;
            var list = this.value().split(',');
            _.each(list, function (value, index) {
                if (value.length > 0) {
                    self.list.push(value.trim());
                }
            });

            return this;
        },

        initObservable: function () {
            this._super();
            this.observe(['valueArea']);
            this.observe('list', this.list);
            return this;
        },

        onUpdateArea: function (value) {
            if (value.length > 1) {
                if (value.indexOf(',') !== -1 || value.indexOf(' ') !== -1) {
                    var newValue = value.slice(0, -1);
                    this.correctValue(newValue);
                }
            }
        },

        correctValue: function (tag) {
            if (this.hasTag(tag)) {
                this.valueArea('');
                return false;
            }
            if (this.isValidTag(tag).passed) {
                this.list.push(tag);
                this.joinList(this.list());
                this.valueArea('');
                return true;
            }

            return false;
        },

        isValidTag: function (tag) {
            return validator('validate-alphanum', tag);
        },

        OnBlurEvent: function (object) {
            if (this.valueArea() && this.valueArea().length > 0) {
                if (!this.correctValue(this.valueArea())) {
                    this.valueArea('');
                }
            }
        },

        deleteTag: function (self, value, event) {
            event ? event.stopPropagation() : false;
            var key = -1;
            _.each(this.list(), function (element, index) {
                if (value === element) {
                    key = index;
                }
            });
            if (key > -1) {
                this.list.splice(key, 1);
                this.joinList(this.list());
                this.valueArea('');
            }
        },

        joinList: function (array) {
            this.value(array.join(','));
        },

        hasTag: function (value) {
            return this.list().indexOf(value) !== -1;
        }
    });
});

la plantilla eliminatoria está en camino ...

StackOverflow / Catalog / view / base / web / template / form / element / tags.html

<div class="tags">
    <div class="admin__control-text">
        <div class="apps-share-chips-editor">
            <input class="admin__control-text" type="hidden"
                   data-bind="
        value: value,
        valueUpdate: valueUpdate,
        attr: {
            name: inputName,
            placeholder: placeholder,
            'aria-describedby': noticeId,
            id: uid,
            disabled: disabled
    }"/>
            <span data-bind="foreach: { data: list, as: 'item' }">
                <span class="field-tag-chip">
                <div class="field-tag-content" data-bind="text: item"></div>
                <div class="field-tag-close-before">
                    <span class="field-tag-close" data-bind="event: {click: $parent.deleteTag.bind($parent, $index)}"></span>
                </div>
                </span>
            </span>
            <textarea
                    class="field-tag-input" placeholder="Add more tags..." data-bind="
        event: {change: userChanges, blur: OnBlurEvent},
        hasFocus: focused,
        valueUpdate: valueUpdate,
        value: valueArea
        "></textarea>
        </div>
    </div>
</div>

algún estilo tal vez? ...

StackOverflow / Catalog / view / base / web / css / tags.css

.field-tag-content {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    white-space: nowrap;
}

.field-tag-chip {
    background: #e0e0e0;
    border: 1px solid #e0e0e0;
    display: inline-block;
    -webkit-border-radius: 3px;
    color: #444;
    margin: 4px 1px 0 2px;
    outline: none;
    vertical-align: middle;
    cursor: default;
    padding: 0;
    -webkit-border-radius: 2px;
    border-radius: 2px;
    overflow: hidden;
    padding:5px;
    padding-right:25px;
}

.field-tag-input {
    display: inline-block;
    margin: 10px 4px 0 4px;
    vertical-align: middle;
    background: none;
    border: 0;
    height: 25px;
    outline: 0;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 0 0 0 5px;
    position: relative;
    resize: none;
    width:50%;
}
.field-tag-close-before {
    position:relative;
}
.field-tag-close{
    position: absolute;
    top: -10px;
    right: -5px;
    cursor: pointer;
}

.field-tag-close:before,
.field-tag-close:after {
    content: "";
    position: absolute;
    top: 0px;
    left: 0px;
    width: 15px;
    height: 4px;
    background: #303030;
}

.field-tag-close:before {
    webkit-transform: rotate(45deg);
    transform: rotate(45deg);
}

.field-tag-close:after {
    webkit-transform: rotate(-45deg);
    transform: rotate(-45deg);
}

¿Por qué poner todo en el view/base? No tengo una respuesta clara para eso, pero me parece correcto porque el equipo de Magento también está colocando todos sus elementos de interfaz de usuario view/base. :)

Y finalmente, necesitará agregar su tags.cssal view/adminhtml/layout/catalog_product_edit.xmly al view/adminhtml/layout/catalog_product_new.xml.

Para que sea eso! Ahora su entrada debería verse así:

ui-element-tags

Salud.

Toan Nguyen
fuente