Các mục trên mạng của các mục trong các tệp thành phần UI là gì


16

Trong các tệp cấu hình Thành phần giao diện người dùng của Magento 2, bạn sẽ thường thấy một itemthuộc tính có cùng source- <item name="source" xsi:type="string">block</item>bên dưới.

#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>    

Những lĩnh vực này để làm gì? Tôi hỏi vì có vẻ như chúng không cần thiết. Ví dụ: mô-đun trong kho GitHub này định cấu hình biểu mẫu Thành phần UI đang hoạt động , nhưng không sử dụng các name="source"mục này .

Có ai biết những thứ này name="source"để làm gì không? Tôi biết về cơ chế thành phần UI lấy XML và định cấu hình nó dưới x-magento-initdạng JSON

"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"
    }
},

Được đưa vào một uiElementđối tượng mô hình khung nhìn Knockout dựa trên. Tuy nhiên, không rõ làm thế nào cây lồng nhau của uiElementcác đối tượng mô hình khung nhìn Knockout dựa trên sử dụng các trường mức sourcetrường này.

Nếu tôi nhìn vào uiElement's initModulesphương pháp

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

Tôi thấy đối tượng tham chiếu một thuộc sourcetính và nếu nó không được đặt, sẽ truy cập vào sổ đăng ký cho một đối tượng sử dụng thuộc providertính làm định danh chuỗi / khóa. Có vẻ như giá trị của những sourcevật phẩm này không được sử dụng. Tuy nhiên, có thể chúng được sử dụng bởi mã PHP hoặc một số mã javascript khác. Do đó, câu hỏi của tôi.

Câu trả lời:


7

Các sourcenghĩa là, hoặc nên, các nhà cung cấp dữ liệu. Tuy nhiên, từ những gì tôi có thể nói, <item name="source">nút trong ví dụ XML mà bạn đưa ra không có sự khác biệt có thể đo lường được và có thể được loại bỏ mà không có hậu quả.

Đây là cách tôi đến với nó: trong initModules()phương thức elements/element.js, có một kiểm tra để xem nếu this.sourcelà một chức năng có thể gọi được:

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

Nếu this.sourcekhông phải là một chức năng có thể gọi được, nó sẽ ghi đè lên this.source Thành phần UI từ sổ đăng ký bằng cách sử dụng this.provider. Một lần nữa, đây là provider, mặc dù, và không phải source. Như vậy, nếu nguồn không phải là một chức năng có thể gọi được tại thời điểm đó, nó chỉ đơn giản là tải nhà cung cấp và bản gốc this.sourceđi theo chiều gió.

this.sourcethường là trống rỗng, nhưng trong trường hợp của cms_block_form, this.sourcesẽ được 'block'bắt đầu với. Vì đó là một chuỗi và không phải là một hàm có thể gọi được, nó chỉ đơn giản là bị ghi đè.

Cũng lưu ý rằng Thành phần UI có thể dễ dàng thêm một số logic để đặt thành this.sourcehàm có thể gọi được, dựa trên chuỗi từ XML, trước khi initModules()được chạy.


Bây giờ, tại sao nguồn này ở nơi đầu tiên? Tôi không biết tại sao nó có trong XML, nhưng nó phục vụ một mục đích trong Javascript. Ví dụ, tôi kéo lên grid/columns/column.js. Trong defaults: {}, sau đây là có:

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

Quay lại elements/element.js, điều này được đánh giá trong initModules():

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

Đây là requestModule()phương pháp:

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

Các async()phương pháp được trả về từ registry, và trong initModules(), giao cho tài sản nhất định. Trong trường hợp này, this.sourceđược đặt thành async()phương thức từ sổ đăng ký. Điều này sẽ xảy ra cho bất cứ điều gì bên trong modules:{}, không chỉ source, mà còn làm sáng tỏ những gì xảy ra với sourcemột số thành phần. Các async()chức năng trở về từ là - không đáng ngạc nhiên - một chức năng callable. Kết quả là, điều này đánh giá là sai và bị bỏ qua:

initModules: function () {
    ...

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

    return this;
}, 

Quay lại grid/columns/column.js, sourceđược sử dụng để thay đổi cách sắp xếp lưới.

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

Các async()phương pháp xử lý các chức năng, nhưng ở đây, nó đang kêu gọi các set()phương pháp trên this.source(). Nguồn, hoặc, dataProvidergrid/provider.js, và nó không có một set()phương thức. Đó là cha mẹ element/element.js, mặc dù:

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

Khái niệm set()này có phần đơn giản ở chỗ nó cập nhật giá trị và thông báo cho người đăng ký. Vì vậy, do columns.jskhai báo a source, nó có quyền truy cập trực tiếp vào các phương thức thực thi trên nó dataProvider.


Kết luận: nguồn dường như là những gì được sử dụng, ít nhất là trong các lớp Javascript, với tư cách là nhà cung cấp dữ liệu. Nếu một nguồn được đặt trong một lớp Javascript và là một hàm có thể gọi được, thì nó có thể được sử dụng để thực thi các phương thức trực tiếp trên dataProvider.

Điều này vẫn còn cho tôi một vài câu hỏi:

  • Có thể sử dụng sourcetrong XML để ủy quyền một lớp dataProvider không?
  • Có phải nó được cho là phục vụ một mục đích trong XML nhưng đôi khi bị phản đối?
  • Có bất kỳ lớp cốt lõi nào nhìn vào this.source(từ XML) và làm điều gì đó thú vị với nó trước khi initModules()được chạy không?

1
+1 cho thông tin hữu ích, nhưng kết thúc với cùng một câu hỏi tôi có - những gì sourceđang làm trong các tệp XML đó :)
Alan Storm

7

Đã đi đến "nguồn" (rên rỉ) cho cái này và có vẻ như các <item name="source"/>nút này thực sự là dư thừa. Hoặc, kỹ sư Magento hiện đang phụ trách họ nghĩ rằng họ là người thừa, vì vậy điều đó gần với sự thật như chúng ta sẽ nhận được.


3

Nguồn là khóa sử dụng thành phần ui có thể đọc dữ liệu được cung cấp bởi lớp " DataProvider ". Nó rất hữu ích khi có nhiều tab và trường.

Ví dụ: tham khảo 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>

Các getData()phương pháp trong DataProvider lớp sẽ trả về một mảng với các phím 'khách hàng' và 'địa chỉ' và các trường tương ứng trong lĩnh vực-bộ sẽ được ánh xạ từ nó. Ảnh chụp màn hình hiển thị kết quả của getData()phương pháp.

Đầu ra của phương thức getData () của lớp DataProvider

Sau đó, khi getDataSourceData()phương thức trong Magento \ Ui \ Element \ Form được gọi, nó xử lý dữ liệu trên.

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

Cảm ơn vì đã trả lời. Tuy nhiên, bạn có chắc chắn về điều này? Tôi không chắc là bạn đúng. Có, trên biểu mẫu của khách hàng, dữ liệu JSON có một khóa có tên là khách hàng và khóa đó ngẫu nhiên sử dụng tên tên làm <item name="sourcenút. Tuy nhiên, tôi không thấy bất kỳ mã PHP nào tham chiếu dữ liệu trong nút nguồn. Ngoài ra, biểu mẫu Trang CMS có một <item name="source" xsi:type="string">page</item>nút và dữ liệu nguồn dữ liệu của nó không có pagekhóa. Cuối cùng, nghiên cứu của tôi chỉ ra nó name="dataScope"xác định nơi một trường có giá trị của nó.
Alan Storm

1
vâng, bạn đúng Alan. Trong quá trình gỡ lỗi tôi cũng thấy điều tương tự (về dataScope). Cảm ơn bạn đã làm rõ. Nếu tôi nhận được bất cứ điều gì thêm về "nguồn", tôi sẽ đăng.
Pankaj Bhope
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.