Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dropdown options as RouterLinks. #102

Closed
jwahdatehagh opened this issue Jun 15, 2017 · 6 comments
Closed

Dropdown options as RouterLinks. #102

jwahdatehagh opened this issue Jun 15, 2017 · 6 comments

Comments

@jwahdatehagh
Copy link
Contributor

Overview of the problem

I'm looking for a nice workflow to use buefy dropdowns with routerLink or programmatic vue-router navigation.

Buefy version: ^0.4.0
Vuejs version: ^2.3.3

Description

I tried different approaches:

First:

By just placing a router-link into the b-dropdown-option:

<b-dropdown-option>
  <router-link to="/settings">
    <b-icon icon="cog"></b-icon>
    Settings
  </router-link>
</b-dropdown-option>

This results in bad UX, as the clickable area doesn't fill the entire link option element (li), due to padding set on it.

Solution: Provide some kind of class to adjust the styling of li (e.g. has-link). This would be the easiest and imo most intuitive solution.

Second: (doesn't work)

<!-- `navigateTo(path)` is defined in parent component -->
<b-dropdown-option @click="navigateTo('/settings')">
  <router-link to="/settings">
    <b-icon icon="cog"></b-icon>
    Settings
  </router-link>
</b-dropdown-option>

This would be ok, but apparently the <b-dropdown-option>-element doesn't expose the @click event.

Solution: Expose @click event on <b-dropdown-option>.

Third:

By doing it through programmatic navigation like so:

<b-dropdown position="is-bottom-left" @change="navigate">
  <b-dropdown-option :value="{type: 'link', path: '/settings'}">
    <b-icon icon="cog"></b-icon>
    Settings
  </b-dropdown-option>
</b-dropdown>
export default {
  methods: {
    navigate ({type, path}) {
      if (type === 'link') {
        this.$router.push({ path })
      }
    }
  }
}

As you can see - if you want to handle different kinds of action types, this gets kind of messy. Also, when providing a :value to <b-dropdown-option>, the selected-property of the <b-dropdown>-component is set, highlighting the option element which breaks down as soon as the user navigates to a different path using other means than the dropdown.

Solution: Provide option to handle the usage of selected on <b-dropdown>.

@jwahdatehagh
Copy link
Contributor Author

Update: I found a workaround that's ok (RouterLink as div for easy styling):

<b-dropdown-option class="has-link">
  <router-link to="/settings" tag="div">
    <b-icon icon="cog"></b-icon>
    Settings
  </router-link>
</b-dropdown-option>

and

.has-link {
  padding: 0 !important;
  > div {
    cursor: pointer; // Enable click events on iOS
    padding: 0.5rem 1rem;
  }
}

@rafaberaldo
Copy link
Member

I'll add the has-link prop

@jwahdatehagh
Copy link
Contributor Author

Could you also expose the @click event on b-dropdown-option? I think that would be very useful...

@rafaberaldo
Copy link
Member

  • Add has-link prop to option
  • Add click event to option
  • Fix dropdown disable state (pointer events)

@corbettbarr
Copy link

corbettbarr commented Jun 26, 2017

Thanks for adding the options. Styling is working well for me now, using the has-link prop, and nesting the icon and text within a router-link tag like this:

<b-dropdown-option value="settings" has-link>
  <router-link :to="'/settings'" exact>
    <b-icon icon="gear" />
      Settings
  </router-link>
</b-dropdown-option>

However, the router-link-active and is-selected classes are not in sync if the user navigates to a route without using the menu. For example, if I click on "home" within my menu, and then navigate to "settings" using a link outside the menu, "is-selected" will still be enabled on the "home" dropdown option, while "router-link-active" will be enabled on the correct "settings" route.

Do I need to manually sync these options somehow?

@corbettbarr
Copy link

Regarding my comment/issue above, I figured out how to sync the router-link-active and is-selected classes within the dropdown options. Just make your v-model parameter a computed value that returns this.$route.name, and make sure your dropdown option values match your router names.

kikuomax added a commit to kikuomax/buefy that referenced this issue Sep 18, 2023
…y#101) (buefy#102)

* feat(lib): add copyAppContext

- `utils/helpers.js` introduces a new function `copyAppContext` that
  copies the context from an app to another app. This function is
  necessary to programmatically mount a component; e.g., Modal.

* fix(lib): app context for programmatic Dialog

- Fixes the issue that components and other plugins on the host app were
  not available on a programmatically opened `Dialog`. Copies the app
  context of the host app to a new Vue app mounting `Dialog`.

  `DialogProgrammatic` becomes a class and is associated with the host
  app.

* fix(lib): app context for programmatic Loading

- Fixes the issue that components and other plugins of the host app were
  not available on a programmatically opened `Loading`. Copies the app
  context of the host app to a new Vue app mounting `Loading`.

  `LoadingProgrammatic` becomes a class and is associated with the host
  app.

* fix(lib): app context for programmatic Modal

- Fixes the issue that components and other plugins on the host app were
  not available on a programmatically mounted `Modal`. Copies the app
  context of the host app to a new Vue app mounting `Modal`.

  `ModalProgrammatic` becomes a class and is associated with the host
  app.

* fix(lib): app context for programmatic Notification

- Fixes the issue that components and other plugins on the host app were
  not available on a programmatically mounted `Notification`. Copies the
  app context of the host app to a new Vue app mounting `Notification`.

  `NotificationProgrammatic` becomes a class and is associated with the
  host app.

* fix(lib): app context for programmatic Snackbar

- Fixes the issue that components and other plugins on the host app were
  not available on a programmatically opened `Snackbar`. Copies the app
  context of the host app to a new Vue app mounting `Snackbar`.

  `SnackbarProgrammatic` becomes a class and is associated with the host
  app.

* fix(lib): app context for programmatic Toast

- Fixes the issue that components and other plugins on the host app were
  not available on a programmatically opened `Toast`. Copies the app
  context of the host app to a new Vue app mounting `Toast`.

  `ToastProgrammatic` becomes a class and is associated with the host
  app.

* fix(docs): programmatic Modal example

- Removes workarounds in the example of a programmatically opened
  `Modal` because the issue that components and other plugins on the
  host app were not available on a programmatically opened `Modal` was
  fixed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants