Last active
September 18, 2023 10:49
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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... | |
* }); | |
*/ |
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?
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
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:
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.