Dynamisches v-model für sw-select-field nicht erwartetes Ergebnis select.id

Hallo,

[Problem] Aktualisierung von
v-html="templateModel.descriptionSelectedVariantProduct[product.id]"
funktioniert nur bei Eingabe im letzten von dynamisch erstellten sw-select-field’s.

  • Auswahl im ersten generierten sw-select-field wird im Template seine Beschreibung nicht aktualisiert.
  • Auswahl im letzten generierten sw-select-field werden alle
    v-html="templateModel.descriptionSelectedVariantProduct[product.id]"
    mit ihrem zugehörigen (korrekten) Wert überschrieben
    (aktualisiert).

[Erwarted] individuelle id für jedes sw-select-field
[Aktuell] dieselbe id für jedes sw-select-field

Generierung id für sw-select-field:

// sw-base-field/index.js
...
computed: {
    identification() {
        if (this.name) {
            return this.name;
        }

        return `sw-field--${this.id}`;
   }
   ...
}

Ein Skript erstellt mit v-for product in templateModel.components dynamisch sw-select-field’s im Komponenten-Template:

<sw-container v-model="templateModel">
    ...
    <fieldset v-for="product in templateModel.components">
       ...
        <sw-select-field
            ...

templateModel.components ist ein Array mit Produkten

// snippet von dev-console im Browser
...
_data:
    templateModel: Object
        components: Array(2)
            0: Proxy
                [[Handler]]: Object
                [[Target]]: Object
                    active: (...)
                  ...            

Dem sw-select-field wird eine Referenz übergeben:

<sw-select-field
                    v-model="templateModel.valueSelectedProductVariants[product.id]"

Ergänzung
an den Id’s der sw-select-field liegt das Problem nicht. Ich habe die Id’s angepasst;

<sw-select-field
    :name="'sw-field--templateModel-valueSelectedProductVariants' + product.id"
   ...

Am Ergebnis hat sich leider nichts geändert…

Plugin-Skripte

// product-composer-variant-price-configurator-material-cost/index.js
import template from './product-composer-variant-price-configurator-material-cost.html.twig';

const { Component } = Shopware;
const { Criteria } = Shopware.Data;
const { mapState } = Component.getComponentHelper();

Component.register('product-composer-variant-price-configurator-material-cost', {
    template,

    data() {
        return {
            templateModel: {},
        }
    },

    props: {
        taxRate: {
            type: Object,
            required: true,
            default() {
                return {};
            },
        },
        currency: {}
    },

    inject: [
        'repositoryFactory'
    ],

    watch: {
        product() {
            this.__setTemplateModel();
        }

    },

    computed: {
        ...mapState('swProductDetail', [
            'product'
        ]),

        ...mapState('it22ProductComponentPlugin', [
            'productComponents'
        ]),

        productRepository() {
            return this.repositoryFactory.create('product');
        },

        selectedVariantProductRepository() {
            return this.repositoryFactory.create('selected_variant_product');
        },

        unitRepository() {
            return this.repositoryFactory.create('unit');
        },
    },

    created() {
        this.__setTemplateModel();
    },

    methods: {
        /**
         * NOTE: called from template, only setter, no persist
         */
        updateSelectedVariant() {
            const ids = value.split('_');
            const variantProductId = ids[0];
            const parentProductId = ids[1];
            const selectedVariantProduct = this.templateModel.variants[variantProductId];

            this.templateModel.descriptionSelectedVariantProduct[parentProductId] = selectedVariantProduct.description;
            this.templateModel.selectedProductVariants[parentProductId] = selectedVariantProduct;
        },

        __setTemplateModel() {
            this.templateModel = {};
            let templateModel = {
                components: {},
                productUnits: {},
                variants: [],
                productVariants: {},
                selectedProductVariants: {},
                valueSelectedProductVariants: this.__getDefaultValueSelectedProductVariants(),
                descriptionSelectedVariantProduct: []
            };
            this.__getTemplateModelProductComponents()
                .then((productComponents) => {
                    templateModel.components = productComponents;

                    return this.__getTemplateModelProductUnits();
                }).then((units) => {
                units.forEach((unit) => {
                    templateModel.productUnits[unit.id] = unit;
                });

                return this.__getTemplateModelProductVariants();
            }).then((variants) => {
                variants.forEach((variant) => {
                    templateModel.variants[variant.id] = variant;
                })
                let array = [];
                this.__getComponentIds().forEach((productId) => {
                    array[productId] = [];
                    variants.forEach((variant) => {
                        if(variant.parentId === productId) {
                            array[productId].push(variant);
                        }
                    })
                });
                templateModel.productVariants = array;

                return this.__getTemplateModelSelectedVariants();
            }).then((selectedVariants) => {
                selectedVariants.forEach((selectedVariant) => {
                    templateModel.selectedProductVariants[selectedVariant.variantId] = selectedVariant;
                    templateModel.valueSelectedProductVariants[selectedVariant.variantId] =
                        selectedVariant.selectedProductId
                        + '_'
                        + selectedVariant.variantId;
                    templateModel.descriptionSelectedVariantProduct[selectedVariant.variantId] =
                        templateModel
                            .variants[selectedVariant.selectedProductId]
                            .description;
                })

                return templateModel;
            }).then((model) => {
                this.templateModel = model;
            })
        },

        __getTemplateModelProductComponents() {
            return new Promise((resolve) => {
                resolve(this.productComponents);
            })
        },

        __getTemplateModelProductUnits() {
            let unitIds = this.__getUnitIdsFromComponents();
            if(unitIds.length > 0) {
                const criteria = new Criteria();
                criteria.addFilter(
                    Criteria.equalsAny('id', unitIds)
                )
                return this.unitRepository.search(criteria, Shopware.Context.api)
            }
            return [];
        },

        __getTemplateModelProductVariants() {
            const criteria = new Criteria();
            criteria.addFilter(
                Criteria.equalsAny('parentId', this.__getComponentIds())
            );

            return this.productRepository.search(criteria, Shopware.Context.api)
        },

        /**
         * selected variant (childProduct) by its component (parentProduct)
         *
         * @returns {*}
         * @private
         */
        __getTemplateModelSelectedVariants() {
            const criteria = new Criteria();
            criteria.addFilter(
                Criteria.equalsAny('variantId', this.__getComponentIds())
            );

            return this.selectedVariantProductRepository.search(criteria, Shopware.Context.api)
        },

        __getComponentIds() {
            let arr = [];
            this.productComponents.forEach((component) => {
                arr.push(component.id);
            })

            return arr;
        },

        __getUnitIdsFromComponents() {
            let arr = [];
            this.productComponents.forEach((component) => {
                if(null !== component.unitId) {
                    arr.push(component.unitId);
                }
            })

            return arr;
        },

        __getDefaultValueSelectedProductVariants() {
            let arr = [];
            this.__getComponentIds().forEach((element) => {
                arr[element.id] = null
            })

            return arr;
        }
    },
})
<sw-container v-model="templateModel">
    <h3>Materialkosten / Komponente (direkte Kosten)</h3>
    <fieldset v-for="product in templateModel.components">
        <legend>Komponente {{ product.name }}</legend>
        <div>
            <sw-container columns="1fr 2fr" gap="0px 30px">
                <sw-select-field
                    v-model="templateModel.valueSelectedProductVariants[product.id]"
                    placeholder="...wähle Spezifikation"
                    label="Spezifikation Komponentenprodukt"
                    @change="updateSelectedVariant">
                    <option
                        v-for="variant in templateModel.productVariants[product.id]"
                        :value="variant.id + '_' + product.id">
                        {{ variant.name || 'n/a' }}
                    </option>
                </sw-select-field>
                <sw-container
                    class="variant-product-description"
                    v-html="templateModel.descriptionSelectedVariantProduct[product.id]"
                >
                </sw-container>
            </sw-container>
            <sw-container
                columns="3fr 1fr 3fr 1fr 3fr"
                gap="0px 30px"
                class="cnt-price-fields">
            </sw-container>
        </div>
    </fieldset>
</sw-container>

Frage wie muß ich v-model="templateModel.valueSelectedProductVariants[product.id]" konfigurieren, damit jedes select-Feld seine eigene ID bekommt?

Danke und VG

Ich habe mir ein Dummy-Objekt aufgebaut, da hat es funktioniert. Dann das orginale Objekt exakt nach dem Dummy gebaut…jetzt geht es.

Thx