Що таке "вихідні" елементи у файлах компонентів інтерфейсу користувача


17

У файлах конфігурації форм-інтерфейсу Magento 2 ви часто бачите itemатрибут з тим самим source- <item name="source" xsi:type="string">block</item>нижче.

#File: vendor/magento/module-cms/view/adminhtml/ui_component/cms_block_form.xml
<field name="title">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">text</item>
            <item name="label" xsi:type="string" translate="true">Block Title</item>
            <item name="formElement" xsi:type="string">input</item>
            <item name="source" xsi:type="string">block</item>
            <item name="sortOrder" xsi:type="number">20</item>
            <item name="dataScope" xsi:type="string">title</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
        </item>
    </argument>
</field>    

Для чого ці поля? Я запитую, бо, здається, вони не потрібні. Наприклад, модуль у цьому сховищі GitHub конфігурує робочу форму компонентів інтерфейсу , але не використовує ці name="source"елементи.

Хтось знає, для чого ці name="source"предмети? Мені відомо про механіку компонентів інтерфейсу, яка приймає XML і налаштовує його як x-magento-initJSON

"block_id": {
    "type": "form.input",
    "name": "block_id",
    "dataScope": "block_id",
    "config": {
        "component": "Magento_Ui\/js\/form\/element\/abstract",
        "template": "ui\/form\/field",
        "visible": false,
        "dataType": "text",
        "formElement": "input",
        "source": "block"
    }
},

Який подається в uiElementоб'єкт модельного виду Knockout view. Однак незрозуміло, як вкладене дерево на uiElementоснові об'єктів моделей перегляду на основі нокауту використовує ці поля на рівні sourceполя.

Якщо я дивлюся на uiElement«S initModulesметод

    initModules: function () {
        _.each(this.modules, function (name, property) {
            if (name) {
                this[property] = this.requestModule(name);
            }
        }, this);

        if (!_.isFunction(this.source)) {
            this.source = registry.get(this.provider);
        }

        return this;
    },

Я бачу, що об'єкт посилається на sourceвластивість, і якщо його не встановлено, потрапить до реєстру для об'єкта, використовуючи providerвластивість як ідентифікатор рядка / ключа. Це здається , що вартість цих sourceпредметів не використовується. Однак можливо, що вони використовуються кодом PHP або іншим кодом javascript. Отже, моє запитання.

Відповіді:


7

Постачальник даних sourceє або повинен бути. Однак, з того, що я можу сказати, <item name="source">вузол у прикладі XML, який ви навели, не може змінити різниці, і його можна усунути без наслідків.

Ось як я прийшов до цього: у initModules()методі elements/element.js, є перевірка, щоб перевірити, чи this.sourceє функція, що викликається:

if (!_.isFunction(this.source)) {
    this.source = registry.get(this.provider);
}

Якщо this.sourceце не функція, яку можна викликати, вона перевизначає this.source компонент інтерфейсу з реєстру за допомогою this.provider. Знову ж таки, цеprovider , але не той source. Таким чином, якщо джерело не є функцією дзвінка в той момент, воно просто завантажує постачальника, а оригінал this.sourceйде шляхом вітру.

this.sourceчасто порожньо, але у випадку з cms_block_form,this.source було б 'block'почати з. Оскільки це є рядком, а не функцією дзвінка, вона просто переосмислена.

Також зауважте, що компонент інтерфейсу може легко додати певну логіку для встановлення this.sourceфункції дзвінка, заснованої на відключенні рядка від XML, ранішеinitModules() запускатись.


Тепер, чому це джерело там в першу чергу? Я не знаю, чому це в XML, але він служить цілі в Javascript. Для прикладу я підтягнувся grid/columns/column.js. В defaults: {}, є наступне:

modules: {
    source: '${ $.provider }'
}

Назад elements/element.jsце оцінюється в initModules():

_.each(this.modules, function (name, property) {
    if (name) {
        this[property] = this.requestModule(name);
    }
}, this);

Ось requestModule()метод:

requestModule: function (name) {
    var requested = this._requesetd;
    if (!requested[name]) {
        requested[name] = registry.async(name);
    }
    return requested[name];
},

async()Метод повертається з реєстру, і initModules(), привласнюється властивості даного. У цьому випадку this.sourceвстановлюється async()метод з реєстру. Це трапиться для будь-якого modules:{}, не тільки source, але проливає світло на те, що відбувається з sourceдеякими компонентами. async()Функція повертається з це - не дивно - викликається,. В результаті це оцінюється як хибне і пропускається:

initModules: function () {
    ...

    if (!_.isFunction(this.source)) {
        this.source = registry.get(this.provider);
    }

    return this;
}, 

Назад grid/columns/column.js, sourceвикористовується для зміни сортування сітки.

exportSorting: function () {
    ...
    this.source('set', 'params.sorting', {
        field: this.index,
        direction: this.sorting
    });
},

async()Метод обробляє функціональність, але тут, це виклик set()методу на this.source(). Джерело, або, dataProviderє grid/provider.jsі у нього немає set()методу. element/element.jsОднак це батько :

set: function (path, value) {
    var data = this.get(path),
        diffs;

    diffs = !_.isFunction(data) && !this.isTracked(path) ?
        utils.compare(data, value, path) :
        false;

    utils.nested(this, path, value);

    if (diffs) {
        this._notifyChanges(diffs);
    }

    return this;
},

Концепція з set()дещо проста у тому, що він оновлює значення та повідомляє передплатників. Отже, в результаті columns.jsоголошення "А" sourceвін має прямий доступ до виконання методів на ньомуdataProvider .


Висновок: джерелом видається те, що використовується як мінімум у класах Javascript як постачальник даних. Якщо джерело встановлено в класі Javascript і є функцією дзвінка, його можна використовувати для виконання методів безпосередньо на dataProvider.

Однак у мене залишається ще кілька питань:

  • Чи можна використовувати source в XML для проксі-класу dataProvider?
  • Чи повинно було служити цілі в XML, але застаріло в якийсь момент?
  • Чи є основні класи, які переглядають this.source(з XML) і роблять з ним щось цікаве, перш ніж initModules()запускається?

1
+1 для корисної інформації, але закінчую тим самим питанням, яке я маю - що sourceробити з цими XML-файлами :)
Alan Storm

7

Пішов до "джерела" (стогін) для цього, і схоже, що ці <item name="source"/>вузли справді є зайвими. Або інженер Magento, який зараз керує ними, вважає, що вони надлишкові, тож це наближене до істини, як ми отримаємо.


3

Джерело - ключ, за допомогою якого компонент ui може читати дані, надані " DataProvider" " ". Це дуже корисно, коли є кілька вкладок і наборів полів.

Наприклад: див module-customer/view/base/ui_component/customer_form.xml

<fieldset name="customer">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Account Information</item>
        </item>
    </argument>
    <field name="entity_id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="visible" xsi:type="boolean">false</item>
                <item name="dataType" xsi:type="string">text</item>
                <item name="formElement" xsi:type="string">input</item>

                **<item name="source" xsi:type="string">customer</item>**

            </item>
        </argument>
    </field>
. 
. 
.

<fieldset name="address">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="is_collection" xsi:type="boolean">true</item>
            <item name="label" xsi:type="string" translate="true">Addresses</item>
            <item name="removeMessage" xsi:type="string" translate="true">Are you sure you want to delete this item?</item>
        </item>
    </argument>
    <field name="parent_id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="visible" xsi:type="boolean">false</item>
                <item name="dataType" xsi:type="string">number</item>
                <item name="formElement" xsi:type="string">input</item>

                **<item name="source" xsi:type="string">address</item>**

            </item>
        </argument>
    </field>

getData()Метод в DataProvider класі буде повертати масив з ключами «клієнт» і «адресу» і відповідні поля в поле наборів будуть відображатися з нього. На екрані знімка відображається результат getData()методу.

Вихід методу getData () класу DataProvider

Потім, коли getDataSourceData()метод у Magento \ Ui \ Component \ Form називається, він обробляє вищезазначені дані.

public function getDataSourceData()
{
    $dataSource = [];

    $id = $this->getContext()->getRequestParam($this->getContext()->getDataProvider()->getRequestFieldName(), null);
    $filter = $this->filterBuilder->setField($this->getContext()->getDataProvider()->getPrimaryFieldName())
        ->setValue($id)
        ->create();
    $this->getContext()->getDataProvider()
        ->addFilter($filter);

    $data = $this->getContext()->getDataProvider()->getData();

    if (isset($data[$id])) {
        $dataSource = [
            'data' => $data[$id]
        ];
    } elseif (isset($data['items'])) {
        foreach ($data['items'] as $item) {
            if ($item[$item['id_field_name']] == $id) {
                **$dataSource = ['data' => ['general' => $item]];**
            }
        }
    }
    return $dataSource;
}

Дякую за відповідь. Однак ви впевнені в цьому? Я не впевнений, що ти прав. Так, у формі клієнта у даних JSON є ключ з іменем клієнта, і цей ключ збігом випадково використовує ім'я імені як <item name="sourceвузол. Однак я не бачу PHP-коду, який би посилався на дані у вихідному вузлі. Також у формі сторінки CMS є <item name="source" xsi:type="string">page</item>вузол, і в його джерелах даних немає pageключа. Нарешті, моє дослідження вказує на те, name="dataScope"що визначає, де поле отримує свої значення.
Алан Шторм

1
так, ти правий Алан. Під час налагодження я також бачив те саме (про dataScope). Дякуємо за роз’яснення. Якщо я отримаю щось більше про "джерело", я опублікую.
Pankaj Bhope
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.