akveo / nebular

:boom: Customizable Angular UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/nebular
MIT License
8.06k stars 1.51k forks source link

Nb Menu with query params are highlighting the first one always even if you have more menu items and selected different one #2033

Open Gobikannan opened 5 years ago

Gobikannan commented 5 years ago

Nb Menu with query params are highlighting the first one always even if you have more menu items and different one selected.

https://github.com/akveo/nebular/blob/978a45c33bba40bb01c6f4b4c3b977990d2c291d/src/framework/theme/components/menu/menu.service.ts#L378

I looked at the code and I see the fragment was checked but not query params.

Is this a known issue?

Gobikannan commented 5 years ago

Here is the example:

https://nebular-menu-query-params-active.stackblitz.io/about?code=2

https://stackblitz.com/edit/nebular-menu-query-params-active

PFA

image

Gobikannan commented 5 years ago

@yggg @nnixaa - any workaround or suggestions on this?

AvshT commented 4 years ago

Try to use the url propery instead

https://stackblitz.com/edit/nebular-menu-query-params-active-nzzoq5?file=src/app/app.component.ts

naonvl commented 4 years ago

any workaround with this? i can't navigate using url

AakashShah14 commented 4 years ago

@yggg @nnixaa - any workaround or suggestions on this?

Broderick890 commented 3 years ago

@yggg the same issue

emicanonica commented 3 years ago

You can always add another path to your routing.module linked to the same component, then you add it to the menu with the query parameter

fdiogoc commented 3 years ago

any workaround or suggestions on this??

BuddyFloyd commented 2 years ago

Had the same problem:

You can use the fragment attribute of the NbMenuItem.

As you can see in https://github.com/akveo/nebular/blob/master/src/framework/theme/components/menu/menu.service.ts#L396 its used as a unique identifer for every nbmenuitem in the selection

EFritzsche90 commented 2 years ago

@BuddyFloyd : Do you have an example for this? I have no clue, what to enter as fragment, so that the menu item is selected within the sidebar when using queryParameters.


{
  title: "All tasks",
  link: "/pages/tasks/list"
}, {
  title: "Do immediately",
  link: "/pages/tasks/list",
  queryParams: {
    filter: "filterTasksAllA"
  }
}, {
  title: "Schedule",
  link: "/pages/tasks/list",
  queryParams: {
    filter: "filterTasksAllB"
  }
}
JereSten commented 2 years ago

Using the fragment property did not work properly for me. When calling a page with queries that was not called from the nebular menu, it still selected the first item.

So i just found a working workaround manipulating the behaviour with one event listener and a little bit of code:

      this.router.events.subscribe((val) => {
        this.selectPageWithQueryParam();
      })

Indirectly, my goal with this trigger is to be able to react to a click in the nebular menu. There's also a onItemClick() event provided by menuService, but in this moment it gets triggered, the link has not changed yet. And it's the already changed link i use in my method. So i think it's the best alternative.

So first i implemented a "hasSameQueryParams"-Method which is checking if a page-item has the same queryParams as the current url.

  private hasSameQueryParams(page: NbMenuItem): boolean {
    let params = this.route.snapshot.queryParams;

    if (Object.entries(params).length == 0 || Object.entries(page.queryParams).length == 0) {
      return false;
    }

    for (const [param, value] of Object.entries(params)) {
      let pageParam = page.queryParams[param];
      if (pageParam != value) {
        return false;
      }
    }

    return true;
  }

If the params are matching i manipulate the menu selection using my second method:

private selectPageWithQueryParam() {
    for (const page of this.pageMenuItems) {
      let sameParams = this.hasSameQueryParams(page);

      if (sameParams) {
        // unselect all unrelevant pages
        this.pageMenuItems.forEach(item => {
          item.selected = false;
        });

        // select page with query
        page.selected = true;
        return;
      }
    }
  }

First i go trough all existing menu pages using a for loop. Next step is comparing the query params with the current url using my first method. If the params are matching i first unselect all pages to ensure that only one page will be selected. And finally i select the right page. Thats it :D

EFritzsche90 commented 2 years ago

@Jere2000 Looks good to me. Only thing is, that my menu item is still not selected, because it is still {selected: false} after set it true. Did you face the same problem?