UIコンポーネントファイルの「ソース」アイテムとは


17

Magentoの2のUIフォーム部品のコンフィギュレーションファイルでは、多くの場合、表示されます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リポジトリのモジュールは 、動作するUIコンポーネントフォームを構成しますが、これらのname="source"アイテムは使用しません。

誰もがこれらのname="source"アイテムの目的を知っていますか?XMLを取得し、x-magento-initJSON として構成するUIコンポーネントメカニズムを知っています。

"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ビューモデルオブジェクトにフィードされます。ただし、uiElementベースのKnockoutビューモデルオブジェクトのネストされたツリーがこれらのフィールドレベルsourceフィールドをどのように使用するかは明確ではありません。

uiElementinitModulesメソッドを見ると

    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が呼び出し可能な関数でない場合は、を使用してレジストリのUIコンポーネントでオーバーライド this.sourceしますthis.provider。繰り返しますが、これはですが、providerではありませんsource。そのため、ソースがその時点で呼び出し可能な関数ではない場合、それは単にプロバイダーをロードするだけで、オリジナルthis.sourceは風の道を行きます。

this.source多くの場合、空ですが、の場合にはcms_block_formthis.sourceだろう'block'と開始します。それは文字列であり、呼び出し可能な関数ではないため、単にオーバーライドされます。

また、UIコンポーネントは、実行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.sourceasync()レジストリのメソッドに設定されます。これはmodules:{}、だけsourceでなく内のすべての場合に発生しますがsource、一部のコンポーネントで何が発生するかを明らかにします。async()驚くことではない- -から返される関数である呼び出し可能な機能。その結果、これはfalseと評価され、スキップされます。

initModules: function () {
    ...

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

    return this;
}, 

に戻ってgrid/columns/column.jssourceグリッドの並べ替えを変更するために使用されます。

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

async()この方法は、それが呼んでいる、機能を処理するが、ここではset()上の方法をthis.source()。ソース、または、dataProvidergrid/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()値を更新し、サブスクライバーに通知するという点で、いくぶん単純です。そのため、aをcolumns.js宣言した結果、のsourceメソッドを実行するための直接アクセスがありますdataProvider


結論:ソースは、少なくともJavascriptクラスでデータプロバイダーとして使用されているように見えます。ソースがJavascriptクラスで設定され、呼び出し可能な関数である場合、それを使用してで直接メソッドを実行できますdataProvider

ただし、まだいくつかの質問が残っています。

  • sourcedataProviderクラスをプロキシするためにXMLで使用することは可能ですか?
  • XMLで目的を果たすことを想定していましたが、ある時点で非推奨になりましたか?
  • 実行さthis.sourceれる前に(XMLから)見て、何か面白いことをするコアクラスinitModules()はありますか?

1
有用な情報を得るために+1、しかし、私が持っている同じ質問で終わる- sourceそれらのXMLファイルで何をしているのか:)
アランストーム

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>

DataProviderクラスのgetData()メソッドは、キー「customer」と「address」を含む配列を返し、フィールドセットの対応するフィールドはそこからマップされます。スクリーンショットはメソッドの結果を表示します。getData()

DataProviderクラスのgetData()メソッドの出力

その後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データにcustomerという名前のキーがあり、そのキーは偶然に名前名を<item name="sourceノードとして使用します。ただし、ソースノードのデータを参照するPHPコードは表示されません。また、CMSページフォームには<item name="source" xsi:type="string">page</item>ノードがあり、そのデータソースデータにはpageキーがありません。最後に、私の研究はname="dataScope"、フィールドが値を取得する場所を決定することを示しています。
アランストーム

1
はい、あなたは正しいアランです。デバッグ中にも同じことがわかりました(dataScopeについて)。説明をありがとう。「ソース」についてもっと知りたい場合は投稿します。
パンカイボープ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.