Search code examples
vue.jsvue-componentshopwareshopware6

Update editor view in Shopware admin CMS component


When creating a new CMS element to be used in Shopware's WYSIWYG editor we have three components: one named component, another configComponent and a third named previewComponent.

The configComponent is apparently used to select the configuration for an element, while the component component is used to update the view in the editor. E.g. Display what was selected in the config part. My problem is that it will only update the view in the editor after the user has clicked the save button, which creates a bad user experience – it should update live.

I think I need to somehow $emit an update event when an entity ID has been selected from the configComponent, and then pass on the ID of the selected entity to the component component.

So, I have the following in the component twig:

  <config-component @entity-picked="entityPickedHandler" />

This should, according to how I interpret the documentation, call the "entityPickedHandler" method in component when the entity-picked event is emitted from configComponent.

E.g. This is the event handler method in component:

methods: {
  entityPickedHandler(data) {
    console.log('Event triggered:', data);
  }
}

And from configComponent I then emit the event:

computed: {
  myEntity: {
    get() {
      return this.element.config.entity.value;
    },

    set(value) {
      // this.$set(this.element.data, 'entityId', value);
      this.element.config.entity.value = value;
      console.log('Trying to emit entity-picked event');
      this.$emit('entity-picked', value);
    }
  }
}

This is evidently not working, as the console.log() in entityPickedHandler handler is never outputted. The event should be emitting however.


Solution

  • Getter/Setter can be a bit iffy with the scope. Generally the approach looks to be correct. Maybe try storing the entity in a data property and having a watcher on it.

    data() {
        return {
            entity: this.element.config.entity.value,
        };
    },
    
    watch: {
        entity(value) {
            this.$emit('entity-picked', value);
        },
    },
    
    methods: {
        entityChanged(value) {
            this.element.config.entity.value = value;
            this.entity = value;
        },
    },
    

    Update
    Or as a watcher from within the component component:

    watch: {
        'element.data.entityId': {
            handler() {
                this.entityId = this.element.data.entityId;
            },
            deep: true,
        }
    }
    

    The data can then be updated from configComponent with the following:

    computed: {
        myentity: {
            get() {
                return this.element.config.myEntity.value;
            },
    
            set(value) {
                this.element.config.myentity.value = value;
                this.$set(this.element.data, 'entityId', value);
                this.$emit('element-update', this.element);
            }
        }
    },
    

    The myentitymethod is then used in the v-model of the sw-entity-single-select in configComponent's twig:

    {% block sw_cms_element_team_box_config %}
        <sw-entity-single-select label="testing my entity" entity="myexample_entity" v-model="myentity" />
    {% endblock %}