Erweiterung des Banner-Sliders - Problem beim Hinzufügen einer weiteren Spalte [ExtJs]

Moin, 

im Moment versuche ich eine erweiterte Version des Banner-Slider-Elements zu entwickelt. Die erweitere Version soll am Ende weitere Spalten zu jedem Banner speichern können. Dazu habe ich ein Plugin geschrieben, das die BannerSlider-Componente und das Bannerslider-Model erweitert. Die Banner-Auswahl funktioniert soweit und es wird auch die zusätzliche Spalte “Size” anzeigt, nur leider wird diese nicht mit abgespeichert. Jemand eine Idee? An irgendeiner Stelle wird wieder auf das alte Model zugegriffen, sodass nach dem Speichern das Feld “Size” nicht in der BannerStore-Variable vorhanden ist.

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

    /**
     * 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-masonry-gallery',

    /**
     * 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}',

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

        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
            }
        }, {
            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.MasonryGalleryWidgetModel', {
                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')
            });
            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);

    },

});



Ext.define('Shopware.apps.Emotion.model.MasonryGalleryWidgetModel', {
    /**
     * 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'
    ]
});

 

Beste Grüße,

Lasse

Ok, das hat nicht lange gedauert… Nächstes Mal sollte ich wohl etwas genauer arbeiten. Habe den Zugriff auf die alte Version des Models in der Compomente des BannerSliders gefunden:

    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.MasonryGalleryWidgetModel', item));
            });
        }
    },

 

Hallo Im02,

wir haben momentan das gleiche Problem, allerdings scheint deine Lösung leider nicht zu funktionieren: das Model wird einfach ignoriert.

Hast du oder hat jmd vll eine andere Lösung? Das wäre wirklich nett!

Liebe Grüße

 

@pr_olga schrieb:

Hallo Im02,

wir haben momentan das gleiche Problem, allerdings scheint deine Lösung leider nicht zu funktionieren: das Model wird einfach ignoriert.

Hast du oder hat jmd vll eine andere Lösung? Das wäre wirklich nett!

Liebe Grüße

Hi pr_olga,

hier mal die gesamte ExtJS Komponente, vielleicht hilft es dir weiter.

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

    /**
     * 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-masonry-gallery-v2',

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

        console.log(me);

        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.MasonryGalleryWidgetModelV2', {
                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'), 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.MasonryGalleryWidgetModelV2', item));
            });
        }
    },

});


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

    /**
     * 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.MasonryGalleryWidgetModelV2', {
    /**
     * 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}

 

 

1 Like

Hallo Im02!

Danke für Deine schnelle Antwort, allerdings werden die Daten immer noch nicht gespeichert, unsere Komponente ist Deiner Komponente absolut identisch.

Wir verzweifeln schon langsam… Vll liegt es an der Ordner-Struktur

unsere SW-Version 5.5.7

Danke!

Hallo pr_olga,

meine Ordnerstruktur sieht folgendermaßen aus:

Hier ist auch noch der Inhalt meiner Plugin-Komponente:

 'onPostDispatchBackendEmotion',
            'Shopware_Controllers_Widgets_Emotion_AddElement' => 'onEmotionAddElement'
        ];
    }

    public function install(InstallContext $context)
    {
        $this->createMasonryGalleryElement();
    }

    public function onPostDispatchBackendEmotion(\Enlight_Controller_ActionEventArgs $args)
    {
        $controller = $args->getSubject();
        $view = $controller->View();

        $view->addTemplateDir($this->getPath() . '/Resources/views/');
        $view->extendsTemplate('backend/emotion/masonry_gallery_widget/view/detail/elements/masonry_gallery_widget.js');
    }

    public function onEmotionAddElement(\Enlight_Event_EventArgs $args)
    {
        $element = $args->get('element');

        if($element['component']['xType'] == 'emotion-masonry-gallery') {
            $data = $args->getReturn();

            $mediaIds = array_column($data['banner_slider'], 'mediaId');
            $context = $this->container->get('shopware_storefront.context_service')->getShopContext();
            $media = $this->container->get('shopware_storefront.media_service')->getList($mediaIds, $context);

            $values = array();
            foreach ($data['banner_slider'] as $file) {
                $single = $media[$file['mediaId']];
                $single = $this->container->get('legacy_struct_converter')->convertMediaStruct($single);
                array_push($values, (array_merge($file, $single)));
            }
            $data['values'] = $values;

            $args->setReturn($data);
        } else {
            return;
        }


    }

    public function createMasonryGalleryElement() {
        $installer = $this->container->get('shopware.emotion_component_installer');

        $element = $installer->createOrUpdate(
            $this->getName(),
            'Masonry Gallery',
            [
                'name' => 'Masonry Gallery',
                'xtype' => 'emotion-masonry-gallery',
                'template' => 'emotion_masonry_gallery',
                'cls' => 'emotion_masonry_gallery',
                'description' => 'A gallery element for the shopping worlds.'
            ]
        );

        $element->createTextField(
            [
                'name' => 'width',
                'fieldLabel' => 'Width',
                'supportText' => 'Enter the width of the images you want to embed.',
                'allowBlank' => false,
                'defaultValue' => '600'
            ]
        );

        $element->createTextField(
            [
                'name' => 'filter',
                'fieldLabel' => 'Filter',
                'supportText' => 'Enter the filter of the images',
                'allowBlank' => true,
                'defaultValue' => ''
            ]
        );

        $element->createCheckboxField([
            'name' => 'shuffle',
            'fieldLabel' => 'Shuffle',
            'supportText' => 'Shuffle order of images',
            'allowBlank' => true,
        ]);

        $element->createHiddenField([
            'name' => 'banner_slider',
            'valueType' => 'json',
        ]);

    }
}

Und services.xml:

            %masonry_gallery_widget.plugin_dir%

Evtl. findest du dadurch noch irgendwelche Unterschiede.

gruß lm02

 

1 Like

Achja und ich benutze zur Zeit die Version 5.6. Mit der 5.5.7 funktionierte es aber auch problemlos.

1 Like

Hallo Im02,

vielen Dank für Deine Hilfe!!! Das Problem war das

        $element->createHiddenField([
            'name' => 'banner_slider',
            'valueType' => 'json',
        ]);

Das Feld fehlte in meinem Plugin, deswegen wurde es nicht gespeichert, den Rest habe ich so belassen, wie es bei mir war. 

Danke vielmals und schöne Feiertage ;-)