Komponen Kotak Magento tidak Menyortir dengan Benar

16

Saya telah mengkonfigurasi komponen grid di Magento - dan perilaku penyortiran tampaknya rusak. Di mana saya bisa men-debug ini pada tingkat javascript, dan / atau apakah ada orang lain yang tahu mengapa ini mungkin terjadi?

Jika saya mengurutkan grid sekali, permintaan ajax dibuat, dan semuanya mengurutkan dengan benar.

masukkan deskripsi gambar di sini

Namun, jenis kedua, tanpa permintaan ajax, menjadikan kisi-kisi dengan semua ID yang sama.

masukkan deskripsi gambar di sini

Perilaku ini tidak terulang pada grid inti Magento, jadi saya cukup yakin ini adalah sesuatu yang saya lakukan. Saya hanya tidak tahu sistem komponen ui cukup baik untuk mengetahui di mana harus mulai debugging ini.

Alan Storm
sumber

Jawaban:

21

Baiklah, saya belum bisa berpura-pura mengerti mengapa, tetapi masalahnya adalah dataargumen dari dataProviderargumen saya .

<!-- ... -->
<argument name="dataProvider" xsi:type="configurableObject">
    <!-- ... --->
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="update_url" xsi:type="url" path="mui/index/render"/>
        </item>
    </argument>
    <!-- ... -->
</argument>
<!-- ... -->

Ketika saya membandingkan ini dengan beberapa grid inti, dataargumen itu hilang sebuah storageConfignode, dengan indexFieldsub-node dengan kunci utama model saya.

<argument name="data" xsi:type="array">
    <item name="config" xsi:type="array">
        <item name="update_url" xsi:type="url" path="mui/index/render"/>
        <item name="storageConfig" xsi:type="array">
            <item name="indexField" xsi:type="string">pulsestorm_commercebug_log_id</item>
        </item>                    

    </item>                          
</argument>

Ketika saya menambahkan node ini, fungsi sortir dipulihkan.

Alan Storm
sumber
Hanya berlari ke masalah yang sama, saya membayangkan itu jatuh kembali atau memuat nilai dari penyimpanan dengan indeks baris daripada id baris data, meskipun tidak masuk akal mengapa data digandakan. Terima kasih atas jawabannya.
LM_Fielding
7

TL; DR

Ini memang masalah yang menarik.

Inilah cara saya memahami sistem tetapi saya mungkin tidak 100% benar.

Seperti yang Anda lihat mengklik kolom tajuk menghasilkan permintaan AJAX ke rute berikut: /admin_key/mui/index/renderdengan parameter berikut:

  • filter [placeholder]
  • isAjax
  • namespace
  • paging [saat ini]
  • paging [pageSize]
  • Cari
  • menyortir [arah]
  • sortir [bidang]

Yang terakhir adalah bidang tempat Anda menyortir kisi Anda.

Rute ini dinyatakan secara default di app/code/Magento/Ui/view/base/ui_component/etc/definition.xml:

<insertListing class="Magento\Ui\Component\Container">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Ui/js/form/components/insert-listing</item>
            <item name="update_url" xsi:type="url" path="mui/index/render"/>
            <item name="render_url" xsi:type="url" path="mui/index/render"/>
            <item name="autoRender" xsi:type="boolean">false</item>
            <item name="dataLinks" xsi:type="array">
                <item name="imports" xsi:type="boolean">true</item>
                <item name="exports" xsi:type="boolean">false</item>
            </item>
            <item name="realTimeLink" xsi:type="boolean">true</item>
        </item>
    </argument>
</insertListing>

Tetapi dalam daftar XML ui_component juga dinyatakan:

        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                <item name="update_url" xsi:type="url" path="mui/index/render"/>
                <item name="storageConfig" xsi:type="array">
                    <item name="indexField" xsi:type="string">page_id</item>
                </item>
            </item>
        </argument>

Rute ini ditangani app/code/Magento/Ui/Controller/Adminhtml/Index/Render.phpberdasarkan parameter namespace (yang biasanya nama Komponen UI Anda)

public function execute()
{
    if ($this->_request->getParam('namespace') === null) {
        $this->_redirect('admin/noroute');
        return;
    }

    $component = $this->factory->create($this->_request->getParam('namespace'));
    $this->prepareComponent($component);
    $this->_response->appendBody((string) $component->render());
}

Di mana prepareComponentmetode ini bersifat rekursif pada komponen anak:

protected function prepareComponent(UiComponentInterface $component)
{
    foreach ($component->getChildComponents() as $child) {
        $this->prepareComponent($child);
    }
    $component->prepare();
}

Ketika komponen kolom disiapkan, penyortiran kolom ditangani oleh app/code/Magento/Ui/Component/Listing/Columns/Column.php:

public function prepare()
{
    $this->addFieldToSelect();

    $dataType = $this->getData('config/dataType');
    if ($dataType) {
        $this->wrappedComponent = $this->uiComponentFactory->create(
            $this->getName(),
            $dataType,
            array_merge(['context' => $this->getContext()], (array) $this->getData())
        );
        $this->wrappedComponent->prepare();
        $wrappedComponentConfig = $this->getJsConfig($this->wrappedComponent);
        // Merge JS configuration with wrapped component configuration
        $jsConfig = array_replace_recursive($wrappedComponentConfig, $this->getJsConfig($this));
        $this->setData('js_config', $jsConfig);

        $this->setData(
            'config',
            array_replace_recursive(
                (array)$this->wrappedComponent->getData('config'),
                (array)$this->getData('config')
            )
        );
    }

    $this->applySorting();

    parent::prepare();
}

Di mana applySorting()metode ini didasarkan pada parameter pengurutan dan itu hanya menambahkan urutan ke penyedia data:

protected function applySorting()
{
    $sorting = $this->getContext()->getRequestParam('sorting');
    $isSortable = $this->getData('config/sortable');
    if ($isSortable !== false
        && !empty($sorting['field'])
        && !empty($sorting['direction'])
        && $sorting['field'] === $this->getName()
    ) {
        $this->getContext()->getDataProvider()->addOrder(
            $this->getName(),
            strtoupper($sorting['direction'])
        );
    }
}

Setelah setiap komponen disiapkan, kelas tindakan membuat komponen (lagi secara rekursif) untuk respons:

$this->_response->appendBody((string) $component->render());

Saya rasa itu adalah langkah-langkah PHP penting dari apa yang terjadi selama penyortiran.

Sekarang untuk JS, render dan pembaruan URL (dideklarasikan di definition.xmlatas) ditugaskan ke elemen di app/code/Magento/Ui/view/base/web/js/form/components/insert.js:

return Element.extend({
    defaults: {
        content: '',
        template: 'ui/form/insert',
        showSpinner: true,
        loading: false,
        autoRender: true,
        visible: true,
        contentSelector: '${$.name}',
        externalData: [],
        params: {
            namespace: '${ $.ns }'
        },
        renderSettings: {
            url: '${ $.render_url }',
            dataType: 'html'
        },
        updateSettings: {
            url: '${ $.update_url }',
            dataType: 'json'
        },
        imports: {},
        exports: {},
        listens: {},
        links: {
            value: '${ $.provider }:${ $.dataScope}'
        },
        modules: {
            externalSource: '${ $.externalProvider }'
        }
    }

Masih dalam file ini, ada requestDatametode yang digunakan untuk mengambil data AJAX:

    requestData: function (params, ajaxSettings) {
        var query = utils.copy(params);

        ajaxSettings = _.extend({
            url: this['update_url'],
            method: 'GET',
            data: query,
            dataType: 'json'
        }, ajaxSettings);

        this.loading(true);

        return $.ajax(ajaxSettings);
    }

Anda dapat melihat bahwa metode ini dipanggil ketika render()metode ini disebut:

        $.async({
            component: this.name,
            ctx: '.' + this.contentSelector
        }, function (el) {
            self.contentEl = $(el);
            self.startRender = true;
            params = _.extend({}, self.params, params || {});
            request = self.requestData(params, self.renderSettings);
            request
                .done(self.onRender)
                .fail(self.onError);
        });

Setelah ini dilakukan, metode panggilan balik dipanggil untuk menerapkan data. Itu adalah onRender():

    onRender: function (data) {
        this.loading(false);
        this.set('content', data);
        this.isRendered = true;
        this.startRender = false;
    }

Saya rasa di situlah konten baru diterapkan.

Raphael di Digital Pianism
sumber
Code Columbo ...
LM_Fielding