primefaces / primeng

The Most Complete Angular UI Component Library
https://primeng.org
Other
10.35k stars 4.58k forks source link

Tabmenu - class ui-state-active is not set correctly on <a> and <li> elements when routing with guards #4197

Closed fxmfr closed 4 years ago

fxmfr commented 7 years ago

I'm submitting a ...

[X] bug report => Search github for a similar issue or PR before submitting
[ ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35

Plunkr Case (Bug Reports) http://plnkr.co/edit/6QjDRAyY6u72olX7qPXS?p=preview

Current behavior When routing with guards (CanActivate, CanDeactivate) active items of tabmenu getting out of sync with router. Maybe other menu components are affected as well.

Expected behavior Active classes should always reflect routers current route/url.

Minimal reproduction of the problem with instructions In plunkr above:

ui-state-active classes should only be added to tab 2.

What is the motivation / use case for changing the behavior? Users should see correct activated tab corresponding to the current url.

Please tell us about your environment: Windows 10

sabithpocker commented 6 years ago

Is this fixed already? Or a workaround while this is being fixed? I have the same issue with Tabs when traversing to a route with multiple Guards. It ends up marking previously active tab's li as active and currenty active tabs a as active. We can even get rid of this and only toggle router-link-active class in parent li only.

UPDATE: I think my issue is different from this, here is a plunker forked from above demonstrating the issue. I am able to reproduce this without guards also:

UPDATE 2: I think this is fixed by this fix. I copied the teplate for li from there and its working fine now

http://plnkr.co/edit/rNgUcq37QmBmOxyh7KN8?p=preview

<!-- INACTIVE TAB(previously active) -->
<li class="ui-tabmenuitem ui-state-default ui-corner-top ui-tabmenuitem-hasicon ui-state-active" ng-reflect-ng-class="[object Object]">
  <a class="ui-menuitem-link ui-corner-all" ng-reflect-router-link="/dashboard" ng-reflect-router-link-active-options="[object Object]" ng-reflect-router-link-active="ui-state-active" href="/dashboard">
    <span class="ui-menuitem-icon fa fa-bars" ng-reflect-klass="ui-menuitem-icon fa" ng-reflect-ng-class="fa-bars"></span>
    <span class="ui-menuitem-text">Dashboard</span>
  </a>
</li>
<!-- ACTIVE TAB -->
<li class="ui-tabmenuitem ui-state-default ui-corner-top ui-tabmenuitem-hasicon" ng-reflect-ng-class="[object Object]">
  <a class="ui-menuitem-link ui-corner-all ui-state-active" ng-reflect-router-link="/orders" ng-reflect-router-link-active-options="[object Object]" ng-reflect-router-link-active="ui-state-active" href="/orders">
    <span class="ui-menuitem-icon fa fa-shopping-cart" ng-reflect-klass="ui-menuitem-icon fa" ng-reflect-ng-class="fa-shopping-cart"></span>
    <span class="ui-menuitem-text">Orders</span>
 </a>
</li>
fxmfr commented 6 years ago

@sabithpocker just to clarify, the problem mentioned here (my issue described above) is not fixed. I'm glad to hear that your issue (which is different from this one) is fixed.

danailvidev commented 6 years ago

If your using canActive and canDeactivate guards and comment line 62 https://github.com/primefaces/primeng/blob/master/src/app/components/tabmenu/tabmenu.ts , then subsribe to this.router.events.subscribe( event => if( event instanceof NavigationEnd) this.activeItems = yourMenuitem[intex]) will work

debunnell commented 5 years ago

A quick workaround is to store the MenuItem from the last successful navigation. Then set the activeItem back to the stored item whenever there is a NavigationCancel event.

The menu item will be selected briefly and then snap back to the previous item but I don't consider that a problem.

@ViewChild(TabMenu) menu: TabMenu;
lastActiveItem: MenuItem;

constructor(
  private router: Router
) { }

ngOnInit() {

  this.router.events.subscribe(e => {
    if(e instanceof NavigationEnd){
      this.lastActiveItem = this.menu.activeItem;
    }
    if(e instanceof NavigationCancel){
      this.menu.activeItem = this.lastActiveItem;
    }
  });
}
yigitfindikli commented 4 years ago

I’m unable to replicate with the latest PrimeNG (you can check at https://www.primefaces.org/primeng/#/tabmenu/info). If the issue still persists with the new version please create a new issue with our stackblitz template.

tamasbege commented 4 years ago

This issue is still present in the 9.0.5 PrimeNG with Angular 8. When using guards with tabmenu, if the navigation is not successful, two tabs remain active. The workaround solves the problem however...