yaminncco / vue-sidebar-menu

A Vue.js Sidebar Menu Component
MIT License
657 stars 193 forks source link

Update active state using vue2 and Inertia #284

Open guifsdev opened 3 weeks ago

guifsdev commented 3 weeks ago

Hi guys, I'm facing an issue with the active state not updating when clicking a menu item when the sidebar is open, i.e., not collapsed. When the item is clicked, the active state remains unchanged. It only updates when not using inertia to navigate between routes. For technical reasons I can't update to vue3 and thus I'm forced to use vue2 branch with Laravel and Inertia. This is an except from my current implementation:

    <sidebar-menu
      :menu="menu"
      :key="route"
      ref="sidebarMenu"
      @item-click.prevent="onItemClick"
    >
    </sidebar-menu>
//
    onItemClick(event, item) {
      if (item.handler) {
        item.handler();
      }
      if (item.href) {
        this.$inertia.visit(item.href);
        this.route = item.href;
      }
      if (!item.child) {
        this.$refs.sidebarMenu.mobileItem = null;
      }
    }

As you can see, I tried with no success to use a "key" so that the component updates when the menu item is clicked. But sort of works, but the active state will be set for the last route, not current. Do you guys have any ideas how can I solve this?

yaminncco commented 3 weeks ago

Instead of using the "key" attr what you can do is create a reactive global property $route then update the value on page change.

//app.js
const route = Vue.observable({ route: '' })
Object.defineProperty(Vue.prototype, '$route', {
  get () {
    return route.route
  },
  set (v) {
    route.route = v
  }
})
methods: {
  onItemClick(event, item) {
    if (item.handler) {
      item.handler();
    }
    if (item.href) {
      this.$inertia.visit(item.href);
    }
    if (!item.child) {
      this.$refs.sidebarMenu.mobileItem = null;
    }
  }
},
watch: {
  $page: function (page) {
    this.$route = page.url
  }
}
guifsdev commented 3 weeks ago

Hi @yaminncco, thank you so much. I ended up sticking to using the key to update the component. For some reason the key was being changed before the inertia.visit call, which was causing the mismatch. So I came to know that Inertia provides a onSuccess handler which I made use as so:

<sidebar-menu :key="route"  @item-click.prevent="onItemClick" </sidebar-menu>
//...
onItemClick() {
  this.$inertia.visit(item.href, {
    onSuccess: () => {
      if (!this.isOnMobile) {
        this.route = item.href;
      }
    }
  });
}

I appreciate the feedback and thanks for this amazing library!