Kullanıcı Arabirimi Bileşen Dosyalarındaki “kaynak” öğeler nelerdir


17

Magento 2'nin UI Form Bileşeni yapılandırma dosyalarında, genellikle aşağıdakilerle bir itemöznitelik görürsünüz source- <item name="source" xsi:type="string">block</item>aşağıda.

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

Bu alanlar ne için? Soruyorum çünkü gerekli olmadıkları anlaşılıyor . Örneğin, bu GitHub veri havuzundaki modül çalışan bir UI Bileşeni formunu yapılandırır , ancak bu name="source"öğeleri kullanmaz .

Bu name="source"eşyaların ne için olduğunu bilen var mı ? XML'yi alan ve x-magento-initJSON olarak yapılandıran UI Bileşeni mekaniğinin farkındayım

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

Hangi uiElementtabanlı bir nakavt görünüm model nesnesine beslenir . Ancak, uiElementtemel Nakavt görünümü model nesnelerinin iç içe ağacının bu alan düzeyi sourcealanlarını nasıl kullandığı açık değildir .

Ben bakarsak uiElementbireyin initModulesyönteme

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

Nesne bir sourceözelliğe başvuruyor görüyorum ve eğer ayarlanmamışsa, providerözelliği bir dize / anahtar tanımlayıcısı olarak kullanan bir nesne için kayıt defterine ulaşacaktır . Osource öğelerin değeri kullanılmıyor gibi görünüyor . Ancak, PHP kodu veya başka bir javascript kodu tarafından kullanılmaları mümkündür. Dolayısıyla sorum.

Yanıtlar:


7

sourceVeri sağlayıcı, ya olmalıdır. Bununla birlikte, söyleyebildiğim kadarıyla, <item name="source">verdiğiniz XML örneğindeki düğüm ölçülebilir bir fark oluşturmaz ve sonuç olmadan kaldırılabilir.

İşte nasıl geldi: initModules()yönteminde, çağrılabilir bir işlev elements/element.jsolup olmadığını görmek için bir kontrol var this.source:

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

this.sourceÇağrılabilir bir işlev değilse , kullanarak kayıt defterinden bir UI Bileşeni ile geçersiz kılar . Yine, bu olsa da, değil . Bu nedenle, kaynak o noktada çağrılabilir bir işlev değilse, yalnızca sağlayıcıyı ve orijinali yükler.this.sourcethis.providerprovidersourcethis.source rüzgarın yolunu açar.

this.sourcegenellikle boştur, ancak söz konusu olduğunda cms_block_form, this.sourceolacağını 'block'başlamak. Bu bir dize olduğundan ve çağrılabilir bir işlev olmadığından, geçersiz kılınır.

Ayrıca, bir UI Bileşeninin çalıştırılmadan this.sourceönce XML'den bir dizeye dayalı olarak çağrılabilir bir işleve ayarlamak için kolayca bazı mantık ekleyebileceğini unutmayın initModules().


Şimdi, bu kaynak neden ilk etapta? Neden XML'de olduğunu bilmiyorum, ancak Javascript'te bir amaca hizmet ediyor. Bir örnek için yukarı çıktım grid/columns/column.js. İçinde defaults: {}aşağıdakiler var:

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

Geri dönersek elements/element.js, bu şu şekilde değerlendirilir initModules():

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

İşte requestModule()yöntem:

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

async()Yöntem kayıt defterinden döndü ve içinde olduğu initModules()verilen özelliğine atanır. Bu durumda, kayıt defterinden yöntem olarak this.sourceayarlanır async(). Bu dahilinde herhangi bir şey için olur modules:{}sadece, sourceama tutuyor ile ne üzerinde ışık sourcebazı bileşenleri. async()Şaşırtıcı olmayan bir şekilde - - dönen fonksiyonu olan bir çağrılabilir fonksiyonu. Sonuç olarak, bu yanlış olarak değerlendirilir ve atlanır:

initModules: function () {
    ...

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

    return this;
}, 

Geri içinde grid/columns/column.js, sourceızgaranın sıralama değiştirmek için kullanılır.

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

async()Yöntem çağırıyor, işlevselliği kolları, ama burada set()üzerinde yöntemini this.source(). Kaynak veya dataProviderolduğu grid/provider.jsve bir yok set()yöntemi. Ebeveyn element/element.js, ama yapar:

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

İle kavramı, set()değerleri güncellemesi ve aboneleri bilgilendirmesi açısından biraz basittir. Bu nedenle, a columns.jsbildiriminin bir sonucu olarak source, üzerinde yöntem yürütmek için doğrudan erişimi vardır dataProvider.


Sonuç: Kaynak, en azından Javascript sınıflarında veri sağlayıcı olarak kullanılan kaynak olarak görünmektedir. Bir kaynak bir Javascript sınıfında ayarlanırsa ve çağrılabilir bir işlevse, yöntemleri doğrudan üzerinde çalıştırmak için kullanılabilir dataProvider.

Yine de bu bana birkaç soru bırakıyor:

  • sourceBir dataProvider sınıfını proxy yapmak için XML'de kullanmak mümkün müdür ?
  • XML'de bir amaca hizmet etmesi gerekiyordu, ancak bir noktada kullanımdan kaldırıldı mı?
  • Çalıştırılmadan this.sourceönce (XML'den) ve ilginç bir şey yapan herhangi bir çekirdek sınıf var initModules()mı?

1
Yararlı bilgiler için +1, ancak aynı soruya sahibim - sourcebu XML dosyalarında ne yapıyor :)
Alan Storm

7

Bunun için "kaynak" (inilti) gitti ve bu <item name="source"/>düğümler aslında gereksiz gibi görünüyor . Ya da, şu anda onlardan sorumlu olan Magento mühendisi gereksiz olduklarını düşünüyor, bu yüzden alacağımız kadar gerçeğe yakın.


3

Kaynak, ui bileşeninin " DataProvider " sınıfı tarafından sağlanan verileri okuyabildiği anahtardır . Birden çok sekme ve alan kümesi olduğunda çok kullanışlıdır.

Örneğin: bakın 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()Yöntem DataProvider'ın sınıfında anahtarları 'müşteri' ve 'adresine' ve saha-kümelerinde ilgili alanlara sahip bir dizi ondan eşleştirilir dönecektir. Ekran görüntüsü, getData()yöntemin sonucunu görüntüler .

DataProvider sınıfının getData () yönteminin çıktısı

Daha sonra getDataSourceData()Magento \ Ui \ Component \ Form içindeki yöntem çağrıldığında yukarıdaki veriler işlenir.

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

Cevap verdiğiniz için teşekkür ederim. Ancak bundan emin misiniz? Doğru olduğundan emin değilim. Evet, müşteri formunda JSON verilerinin müşteri adında bir anahtarı vardır ve bu anahtar, ad olarak tesadüfen <item name="sourcedüğüm olarak kullanılır. Ancak, kaynak düğümdeki verilere başvuran herhangi bir PHP kodu görmüyorum. Ayrıca, CMS Sayfa formunun bir <item name="source" xsi:type="string">page</item>düğümü vardır ve veri kaynağı verilerinin bir pageanahtarı yoktur. Son olarak, araştırmam name="dataScope"bir alanın değerlerini nereden alacağını belirlediğini gösteriyor .
Alan Storm

1
evet haklısın Alan. Hata ayıklama sırasında da aynı şeyi gördüm (dataScope hakkında). Açıklama için teşekkürler. Eğer "kaynak" hakkında bir şey alırsam gönderirim.
Pankaj Bhope
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.