Skip to content

Instantly share code, notes, and snippets.

@james2doyle
Last active September 18, 2023 10:49
Show Gist options
  • Save james2doyle/e19faf122ed6fa3380c38242389c21fe to your computer and use it in GitHub Desktop.
Save james2doyle/e19faf122ed6fa3380c38242389c21fe to your computer and use it in GitHub Desktop.
Support Vue apps inside the Shopify section editor. Supports refreshing the Vue instance when changes happen in the section editor
import Vue from 'vue';
/**
* EventHub to listen or broadcast to all components
*
* @see https://shopify.dev/tutorials/develop-theme-sections-integration-with-theme-editor
*
* Usage: eventHub.$on('shopify:section:select:{my-section-name}', (event) => handleSelect());
*
*/
const eventHub = new Vue({
created() {
const themeEventHandler = (event) => {
// emit a generic version
this.$emit(`${event.type}`, event);
// emit a specific version for the section
this.$emit(`${event.type}:${event.detail.sectionId}`, event);
};
// these are custom events emitted by the Shopify section editor
// we are hooking them up to our Vue event dispatcher
document.addEventListener('shopify:section:load', themeEventHandler);
document.addEventListener('shopify:section:unload', themeEventHandler);
document.addEventListener('shopify:section:select', themeEventHandler);
document.addEventListener('shopify:section:deselect', themeEventHandler);
document.addEventListener('shopify:section:reorder', themeEventHandler);
document.addEventListener('shopify:block:select', themeEventHandler);
document.addEventListener('shopify:block:deselect', themeEventHandler);
}
});
function createApp() {
return new Vue({
el: '#app',
});
}
let instance = createApp();
eventHub.$on('shopify:section:select', ({ detail }) => {
// recreate the Vue app because the section editor destroyed it
if (detail.load) {
instance.$destroy();
instance = createApp();
}
});
/**
* You can also do this in Vue apps
* Our section would be named "navigation" in this instance
*
* import eventHub from 'Functions/event-hub';
* // this would go in mounted()
* eventHub.$on('shopify:section:select:navigation', () => {
* // do something once the section is opened...
* });
* eventHub.$on('shopify:section:deselect:navigation', () => {
* // do something once the section is closed...
* });
*/
@sillycube
Copy link

sillycube commented Jan 16, 2021

Unfortunately, $destroy instance method is also removed in Vue 3.x. So I don't know how to recreate / reload / re-render the app. I can make it work by remounting the app. However, the data reactivity is lost:

  function RemountVueApp() {
    console.log('listen to shopify theme editor re-render');
	//     vm.$forceUpdate(); // not work
    vueApp = createMyApp()
    vueApp.component('product-card', productCard) 
  
  	vm = vueApp.mount('#byobApp') 
    
  }
  
  const emitter = window.mitt();
  emitter.on('shopify:section:load', RemountVueApp);
  
  const themeEventHandler = (event) => {
    // emit a generic version
    emitter.emit(`${event.type}`, event);
  };

  // these are custom events emitted by the Shopify section editor
  // we are hooking them up to our Vue event dispatcher
  document.addEventListener('shopify:section:load', themeEventHandler);

However, I don't know if there is a memory leak if the user continues to edit in the theme editor. So I open a thread on the official forum. You can follow the thread if you're interested.

@james2doyle
Copy link
Author

Hmm not sure. I haven't used vue 3 with shopify yet so I'm not sure how it handles that stuff anymore. Are you sure you still need to recreate the instance?

@sillycube
Copy link

It works now. I tried to create a <style> tag before my <div id="myVueApp">...</div>:

<style>
.test-button {
    background-color: {{ section.settings.button_color }};
  }
</style> 

In my template, I bind the class like this:

<button type="button" id="btnAddToBundle" class="btn" :class="'test-button'" :disabled="!available">
	<span id="AddToCartText" v-if="available">
		Add to Bundle
	</span>
	<span id="AddToCartText" v-else>
		Sold Out
	</span>
</button>

Now look like it works. When I change the button color in the section, it can be updated immediately. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment