Selected Sales Channel in sw-sales-channel-switch

How to get or change the currently selected sales channel in an Shopware sw-sales-channel-switch component.

109 views
d

By. Jacob

Edited: 2024-02-28 17:57

Maybe you need a way to access- or change the currently selected sales channel inside a sw-sales-channel-switch component – creating a $refs that references the switch will both allow you access the selected sales channel id, and change it using the changeToNewSalesChannel method on the reference. E.g:

this.$refs.salesChannelSwitcher.changeToNewSalesChannel(this.newSalesChannelId);

The problem is, since you access the sw-sales-channel-switch component by its $ref, it will not be available before the DOM is loaded. Why? Because the reference is being defined in the template of your vue component. It's a bit of a chicken before the egg problem.

This touches upon a need for a mechanism to basically execute code when something in the DOM is available. E.g. Similar to a traditional onLoad() event handler. Unfortunately, this does not seem to exist in Shopware – or it is poorly documented.

You can of course access it by the click of a button or similar, but sometimes you might want to access it when the DOM has finished loading. E.g. Immediately on first page view. You may think of trying to access it inside the mounted() lifecycle, since this is at least documented as a way of executing code after the DOM loads – but this does not seem to work in Shopware.

Before we get to a solution for that, put a sw-sales-channel-switch inside your .twig template somewhere:

<sw-sales-channel-switch
  @change-sales-channel-id="onSalesChannelChanged" ref="salesChannelSwitcher"
/>

The @change-sales-channel-id event allows you to call a custom method when the user selects a sales channel, and the ID of the selected channel will be provided as an ID to your method.

Now we may access the selected sales channel in our custom onSalesChannelChanged function:

methods: {
  onSalesChannelChanged(salesChannelId) {
    this.salesChannelId = salesChannelId;
  }
}

That is very useful, as it even allow you to use the salesChannelId property in a v-modal on another element, and even have it update both ways. But, what if you need to change the currently selected sales channel in the sw-sales-channel-switch? This is vastly more convoluted, and I even think you should just consider making your own sales channel switcher – it will be easier!

Now, the salesChannelSwitcher is defined as a $ref inside of the template, which means it is not immediately available where you need it; you will need a to wait for it to be defined before you access it. I am not sure this is the best way, but when making Shopware administration plugins, there is a trick to at least do that from the updated() lifecycle hook. E.g:

updated() {
  if (this.$refs.salesChannelSwitcher) {
    console.log('salesChannelSwitcher is defined');
  }
}

The if statement is intended to make sure the code only triggers when the reference has been defined. Unfortunately, that is still not quite enough, because if you pay attention in your console, you will notice that it actually gets triggered multiple times, which could cause unwanted side-effects. To get around that problem you can add a simple counter property, and check that it has not passed 1 in value. First define the property:

data() {
  return {
    updCount: 0
  };
}
if (this.$refs.salesChannelSwitcher && this.updCount == 0) {
  this.updCount++;
  console.log('salesChannelSwitcher is defined:' + this.updCount);
}

The console output should then clearly indicate that the code inside the if statement has only been executed once.

You can then finally update the selected sales channel by calling changeToNewSalesChannel, so the final code should look like this:

updated() {
  if (this.$refs.salesChannelSwitcher && this.updCount == 0) {
    this.updCount++;
    this.$refs.salesChannelSwitcher.changeToNewSalesChannel(this.newSalesChannelId);
  }
}

This will finally switch the selected sales channel in the switcher, and it will make sure it is only being done once, as the switcher first becomes available in the DOM.

Mounted and $nextTick does not seem to work

I am not sure whether this is just a Shopware thing, but I have seen examples using mounted and $nextTick, but I have not been able to get them to work properly for this. E.g. the below will just result in "undefined" being logged to the console:

mounted: function () {
  this.$nextTick(function () {
    if (this.$refs.salesChannelSwitcher) {
      console.log('defined:' + this.$refs.salesChannelSwitcher);
    } else {
      console.log('undefined');
    }
  })
}

Links

  1. sw-sales-channel-switch - component-library.shopware.com

Tell us what you think:

  1. Sometimes we may to manually clear cached Shopware files to fix namespace issues.
  2. How to obtain the currently selected API language from Shopware vue components.
  3. How to access file system paths from storefront twig files in Shopware.
  4. In this tutorial you will learn how to work with Shopware entities in a generic way from PHP, without having to specifically inject the repository in your services.xml file.

More in: Shopware