Is it possible for Shopify to publish an article or blog on with an example on how to use ui-nav-menu (toggle the status of the nav link) without React? This document is so cryptic and I couldn’t find any examples on how to “migrate” to App Bridge v4 without React.
Hey @Ronald_G - this is great idea, I do agree the documentation there is fairly no-frills. I’ll look into this on my end and see if we can share a blog post/guide with you/other folks who may be interested.
Still digging into this for you @Ronald_G , but I wanted to follow up here to share a resource/confirm things so we can help out a bit better. In the migration docs, we do have a section on the nav menu: link here.
Essentially you’d just need to first include the web components src like this in your app:
Then you’d just need to define your menu items like this:
Home
Templates
Settings
Just to confirm the blocker with you, is it because App Bridge 4 derives the active nav item from the current URL, you can’t programmatically force an active item? In your current setup, does UJS intercept navigation without updating window.location/history, so the component never sees the new URL? Let me know and I can look into seeing if I’m able to roll up some further examples to share here if that would be helpful. Feel free to ping me here.
Hope you are well. We finally are getting back to this after BFCM.
We got app_bridge.js to load. However, we are stuck on some probably simple issues:
The migration guide says to use <s-page> instead of .create, however, where does that code actually code? Since TitleBar and NavigationMenuare outside of our app, it’s not clear where to call these code?
We use Rails UJS and in the past, we do this in order to get session token. Is that still needed anymore?
var appBridgeUtils = window[“app-bridge”][‘utilities’];
window.sessionToken = await appBridgeUtils.getSessionToken(app);
Hey @Ronald_G, glad to hear you’re back on this after BFCM, sorry about the delayed reply here, I’ve been OOO for the last little bit.
For your first question about where the web components go, you’d generally want want to add <ui-nav-menu>(link here) in your layout file (like application.html.erb or whichever type of layout you’re using) since it’s a global element that should persist across pages. I’d just make sure you have the meta tag with your API key and the App Bridge script in the head (info here), then drop the nav menu in the body. For page-specific stuff like the title bar, could wrap your view content in <s-page>with a title attribute and slot in any action buttons you need, that goes in your individual view templates rather than the layout.
On the session token question, the old getSessionToken(app) pattern is deprecated, but you do still need to pass a token when making requests to your own Rails backend for authentication. I think for this, you would just want to use: await shopify.idToken()which returns the JWT. So your setup could grab that token and include it in the Authorization header when hitting your Rails endpoints. The shopify_app gem should validate it the same way.
To check this, you can open your browser console while in the embedded app and run shopify.idToken().then(console.log) to confirm you’re getting a valid token back.
Let me know if you hit any snags with that or if anything’s unclear - happy to dig deeper on either piece!
With your help, we were able to implement UJS, NavigationMenu, and partiallyContextualSaveBar (CSB).
However, I’m a little unclear as to how to know when the CSB is shown vs. hidden? Shopify BFS team is requiring that other button like Cancel, Back be disabled or hidden when CSB is shown.
For example, if the CSB has ID = shopify-csb, this doesn’t seem to work.
For detecting when the Contextual Save Bar is shown vs hidden, the approach you’re using is correct, the ui-save-bar element does support show and hide event listeners. I’m wondering if the issue is likely just a timing one where the element needs to exist in the DOM before you add the listener.
Try wrapping it like this:
document.addEventListener('DOMContentLoaded', () => { const saveBar = document.getElementById('shopify-csb'); if (saveBar) { saveBar.addEventListener('show', () => { console.log('CSB showing'); // Disable your Cancel/Back buttons here }); saveBar.addEventListener('hide', () => { console.log('CSB hidden'); // Re-enable your Cancel/Back buttons here }); }});
You can also use the showing getter to check the current state at any time:
const saveBar = document.getElementById('shopify-csb');if (saveBar.showing) { // Save bar is currently visible}
It seems that we don’t have an issue getting the CSB to display, but either addEventListener doesn’t seem to be working, or the CSB isn’t configured correctly?
This is definitely odd. One potential reason for why this may be happening here is that the show and hide events only fire when you use the Save Bar’s built-in methods to control it if you’re not doing that already. So, just having the <ui-save-bar> element in the DOM doesn’t mean App Bridge considers it “shown”, you’d need to explicitly call .show() to trigger that state change if that makes sense.
Somewhere in your app logic (like when a form field is modified), you’d call:
Once you’re using those methods, your event listeners should fire as expected, and the .showing property will correctly return true when the bar is visible.
Here’s a quick example of how you could set this up:
const saveBar = document.getElementById('shopify-csb');saveBar.addEventListener('show', () => { console.log('CSB showing'); // Disable your Cancel/Back buttons here});saveBar.addEventListener('hide', () => { console.log('CSB hidden'); // Re-enable your Cancel/Back buttons here});// Call this when the user makes a changesaveBar.show();
Let me know if that clears things up or if you’re still running into issues, happy to keep chatting on this.