扩展 Shopware Emotion 横幅滑块

Extend Shopware Emotion Banner Slider

我们尝试在 Shopware 中为情感创建自定义横幅滑块。此自定义横幅源自标准情感横幅滑块,并向其添加了一些额外的列。一切正常,没有错误,但是,模型被完全忽略,即来自网格的数据没有保存,所以 add/save 事件没有被触发。 (此问题出现 here 德文) 这是我们的 ExtJS 组件:

/**
 * ExtJS Component for Media Widget Plugin
 */
Ext.define('Shopware.apps.Emotion.view.components.AdvancedBannerSlider', {

    /**
     * Extend from the base emotion component.
     */
    extend: 'Shopware.apps.Emotion.view.components.BannerSlider',

    /**
     * Set the defined xtype of the component as the new widget alias.
     */
    alias: 'widget.emotion-components-advancedbannerslider',

    /**
     * Snippets for the component.
     * @object
     */
    snippets: {
        'select_banner': '{s name=select_banner}Select banner(s){/s}',
        'banner_administration': '{s name=banner_administration}Banner administration{/s}',
        'path': '{s name=path}Image path{/s}',
        'actions': '{s name=actions}Action(s){/s}',
        'link': '{s name=link}Link{/s}',
        'altText': '{s name=altText}Alternative text{/s}',
        'title': '{s name=title}Title{/s}',
        'size': '{s name=size}Größe{/s}',
        'cols': '{s name=cols}Spalten{/s}',
        'filter': '{s name=filter}Filter{/s}',

        banner_slider_title: '{s name=banner_slider_title}Title{/s}',
        banner_slider_arrows: '{s name=banner_slider_arrows}Display arrows{/s}',
        banner_slider_numbers: {
            fieldLabel: '{s name=banner_slider_numbers/label}Display numbers{/s}',
            supportText: '{s name=banner_slider_numbers/support}Please note that this setting only affects the "emotion" template.{/s}'
        },
        banner_slider_scrollspeed: '{s name=banner_slider_scrollspeed}Scroll speed{/s}',
        banner_slider_rotation: '{s name=banner_slider_rotation}Rotate automatically{/s}',
        banner_slider_rotatespeed: '{s name=banner_slider_rotatespeed}Rotation speed{/s}'
    },


    /**
     * Creates the fieldset which holds the banner administration. The method
     * also creates the banner store and registers the drag and drop plugin
     * for the grid.
     *
     * @public
     * @return [object] Ext.form.FieldSet
     */
    createBannerFieldset: function() {
        var me = this;

        me.mediaSelection = Ext.create('Shopware.form.field.MediaSelection', {
            fieldLabel: me.snippets.select_banner,
            labelWidth: 155,
            albumId: -3,
            listeners: {
                scope: me,
                selectMedia: me.onAddBannerToGrid
            }
        });

        me.bannerStore = Ext.create('Ext.data.Store', {
            fields: [ 'position', 'path', 'link', 'altText', 'title', 'mediaId', 'size', 'cols', 'filter' ]
        });

        me.ddGridPlugin = Ext.create('Ext.grid.plugin.DragDrop');

        me.cellEditing = Ext.create('Ext.grid.plugin.RowEditing', {
            clicksToEdit: 2
        });

        me.bannerGrid = Ext.create('Ext.grid.Panel', {
            columns: me.createColumns(),
            autoScroll: true,
            store: me.bannerStore,
            height: 200,
            plugins: [ me.cellEditing ],
            viewConfig: {
                plugins: [ me.ddGridPlugin ],
                listeners: {
                    scope: me,
                    drop: me.onRepositionBanner
                }
            },
            listeners: {
                scope: me,
                edit: function() {
                    me.refreshHiddenValue();
                }
            }
        });

        return me.bannerFieldset = Ext.create('Ext.form.FieldSet', {
            title: me.snippets.banner_administration,
            layout: 'anchor',
            defaults: { anchor: '100%' },
            items: [ me.mediaSelection, me.bannerGrid ]
        });
    },


    /**
     * Helper method which creates the column model
     * for the banner administration grid panel.
     *
     * @public
     * @return [array] computed columns
     */
    createColumns: function() {
        var me = this, snippets = me.snippets;

        return [{
            header: '⚌',
            width: 24,
            hideable: false,
            renderer : me.renderSorthandleColumn
        }, {
            dataIndex: 'path',
            header: snippets.path,
            flex: 1
        }, {
            dataIndex: 'link',
            header: snippets.link,
            flex: 1,
            editor: {
                xtype: 'textfield',
                allowBlank: true
            }
        }, {
            dataIndex: 'altText',
            header: snippets.altText,
            flex: 1,
            editor: {
                xtype: 'textfield',
                allowBlank: true
            }
        }, {
            dataIndex: 'title',
            header: snippets.title,
            flex: 1,
            editor: {
                xtype: 'textfield',
                allowBlank: true
            }
        }, {
            dataIndex: 'size',
            header: snippets.size,
            flex: 1,
            editor: {
                xtype: 'textfield',
                allowBlank: true
            }
        }, {
            dataIndex: 'cols',
            header: snippets.cols,
            flex: 1,
            editor: {
                xtype: 'numberfield',
                allowBlank: true,
                minValue: 1,
                decimalPrecision: 0
            }
        }, {
            dataIndex: 'filter',
            header: snippets.filter,
            flex: 1,
            editor: {
                xtype: 'textfield',
                allowBlank: true
            }
        }, {
            xtype: 'actioncolumn',
            header: snippets.actions,
            width: 60,
            items: [{
                iconCls: 'sprite-minus-circle',
                action: 'delete-banner',
                scope: me,
                handler: me.onDeleteBanner
            }]
        }];
    },


    /**
     * Event listener method which will be triggered when one (or more)
     * banner are added to the banner slider.
     *
     * Creates new models based on the selected banners and
     * assigns them to the banner store.
     *
     * @public
     * @event selectMedia
     * @param [object] field - Shopware.MediaManager.MediaSelection
     * @param [array] records - array of the selected media
     */
    onAddBannerToGrid: function(field, records) {
        var me = this, store = me.bannerStore;

        Ext.each(records, function(record) {
            var count = store.getCount();
            var model = Ext.create('Shopware.apps.Emotion.model.AdvancedBannerSliderModel', {
                position: count,
                path: record.get('path'),
                mediaId: record.get('id'),
                link: record.get('link'),
                altText: record.get('altText'),
                title: record.get('title'),
                size: record.get('size'),
                cols: record.get('cols'),
                filter: record.get('filter')
            });
            store.add(model);
        });

        // We need a defer due to early firing of the event
        Ext.defer(function() {
            me.mediaSelection.inputEl.dom.value = '';
            me.refreshHiddenValue();
        }, 10);

    },

    getGridData: function() {
        var me = this,
            elementStore = me.getSettings('record').get('data'), advancedBannerSlider;
        Ext.each(elementStore, function(element) {
            if(element.key === 'advanced_banner_slider') {
                advancedBannerSlider = element;
                return false;
            }
        });

        if(advancedBannerSlider && advancedBannerSlider.value) {
            Ext.each(bannerSlider.value, function(item) {
                me.bannerStore.add(Ext.create('Shopware.apps.Emotion.model.AdvancedBannerSliderModel', item));
            });
        }
    },

});


//{block name="backend/emotion/controller/massive_widgets"}
//{namespace name=backend/emotion/controller}
Ext.define('Shopware.apps.Emotion.controller.AdvancedBannerSlider', {

    /**
     * Defines an override applied to a class.
     * @string
     */
    extend: 'Shopware.apps.Emotion.controller.Detail'
});
//{/block}


/**
 * Shopware Model - Emotion backend module.
 */
//{block name="backend/emotion/model/banner_slider"}
Ext.define('Shopware.apps.Emotion.model.AdvancedBannerSliderModel', {
    /**
     * Extends the standard Ext Model
     * @string
     */
    extend: 'Shopware.apps.Emotion.model.BannerSlider',

    /**
     * The fields used for this model
     * @array
     */
    fields: [
        //{block name="backend/emotion/model/field/banner_slider"}{/block}
        'position', 'path', 'mediaId', 'link', 'altText', 'title', 'size', 'cols', 'filter'
    ]
});
//{/block}

这是我们插件的结构:

所以如果有必要我可以提供一个 GitLab link。提前致谢!

感谢大家的帮助!问题是 json 格式的横幅滑块的隐藏字段被遗漏了,它给模型带来了数据。所以,解决方案: 1. 将此字段添加到新组件

 $element = $installer->createOrUpdate(
        $this->getName(),
        'advancedbannerslider',
        [
            'name' => 'advancedbannerslider',
            'xtype' => 'emotion-advanced-banner-slider',
            'template' => 'emotion_advanced_banner_slider',
            'cls' => 'emotion_advanced_banner_slider',
            'description' => 'advancedbannerslider'
        ]
    );

$element->createHiddenField([
    'name' => 'banner_slider',
    'valueType' => 'json',
]);
  1. 对上面的代码进行一些调整: alias: 'widget.emotion-advanced-banner-slider',
      getGridData: function() {
            var me = this,
                elementStore = me.getSettings('record').get('data'), bannerSlider;

            Ext.each(elementStore, function(element) {
                if(element.key === 'banner_slider') {
                    bannerSlider = element;
                    return false;
                }
            });

            if(bannerSlider && bannerSlider.value) {
                Ext.each(bannerSlider.value, function(item) {
                    me.bannerStore.add(Ext.create('Shopware.apps.Emotion.model.AdvancedBannerSliderModel', item));
                });
            }
        },