Magento Grid Bileşeni Doğru Sıralamıyor


16

Magento'da bir ızgara bileşeni yapılandırdım - ve sıralama davranışı bozuk görünüyor. Javascript düzeyinde nerede hata ayıklayabilirim ve / veya başka birinin bunun neden olabileceği hakkında bir fikri var mı?

Izgarayı bir kez sıralarsam, bir ajax isteği yapılır ve her şey doğru şekilde sıralanır.

resim açıklamasını buraya girin

Ancak, ajax isteği olmadan ikinci sıralama, ızgarayı aynı kimliklerle oluşturur.

resim açıklamasını buraya girin

Davranış olduğunu değil Magento çekirdek ızgaraları üzerinde tekrar, bu yüzden oldukça emin bu benim yaptığım bir şeydir değilim. UI bileşen sistemini bu hata ayıklamaya nereden başlayacağınızı yeterince iyi bilmiyorum.

Yanıtlar:


21

Pekâlâ, nedenini henüz anlayamıyorum, ama sorun datatartışmamın dataProviderargümanı idi.

<!-- ... -->
<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>
<!-- ... -->

Bunu birkaç temel ızgarayla karşılaştırdığımda, dataargümanda modelimin birincil anahtarına storageConfigsahip bir indexFieldalt düğüm olan bir düğüm eksikti .

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

Bu düğümleri eklediğimde, sıralama işlevi geri yüklendi.


Sadece aynı soruna koştu, veri düşüyor neden anlamsız olsa da, geri düşüyor veya veri satır kimliği yerine satır dizini tarafından değerleri depolama yüklediğini hayal ediyorum. Cevap için teşekkür ederim.
LM_Fielding

7

TL; DR

Bu gerçekten ilginç bir problem.

Sistemi şu şekilde anladım ama% 100 doğru olmayabilirim.

Gördüğünüz gibi başlık sütununa tıklamak, aşağıdaki yola bir AJAX isteği oluşturur /admin_key/mui/index/render:

  • Filtreler [tutucu]
  • isAjax
  • ad
  • çağn akımı []
  • çağn [pageSize]
  • arama
  • sıralama [yön]
  • sıralama [alan]

Sonuncusu ızgaranızı sıraladığınız alandır.

Bu rota varsayılan olarak şu ülkelerde bildirilir 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>

Ancak bir liste ui_component XML'de de ilan edilir:

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

Bu rota, app/code/Magento/Ui/Controller/Adminhtml/Index/Render.phpad alanı parametresine (normalde UI Bileşeninizin adı olan) göre işlenir

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

prepareComponentYöntemin alt bileşenler üzerinde özyinelemeli olduğu durumlarda :

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

Sütun bileşeni hazırlandığında, sütun sıralaması şu şekilde yapılır 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();
}

Burada applySorting()yöntemdir, burada tasnif parametresine dayanarak ve sadece veri sağlayıcısına sipariş verir:

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'])
        );
    }
}

Her bileşen hazırlandıktan sonra, eylem sınıfı bileşeni yanıt için (tekrar tekrar) oluşturur:

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

Ben sıralama sırasında ne önemli PHP adımları olduğunu tahmin.

Şimdi JS'ye, oluşturma ve güncelleme URL'leri ( definition.xmlyukarıda belirtilen) aşağıdaki öğeye atanmıştır 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 }'
        }
    }

Hala bu dosyada, requestDataAJAX verilerini almak için kullanılan bir yöntem var:

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

Yöntem çağrıldığında bu yöntemin render()çağrıldığını görebilirsiniz:

        $.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);
        });

Bu yapıldıktan sonra, verileri uygulamak için bir geri arama yöntemi çağrılır. Bu onRender():

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

Yeni içeriğin uygulandığı yer budur.


Kod Columbo ...
LM_Fielding
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.