router icon indicating copy to clipboard operation
router copied to clipboard

[WebComponent and RouterLocation] General Questions

Open aress31 opened this issue 5 years ago • 8 comments

Hi Vaadin team,

I have a few questions - which answers could be added to the official doc to help other beginners. My application uses the Vaadin router for client-side routing and I am trying to style the links of my nav-bar to reflect the current active view as follows:

  renderLink(route: Route): TemplateResult {
    // TODO: Fix that need to reupdate at each route change
    // console.log(getLocation());
    return html`<a
      class=${location.pathname === route.path ? 'active' : ''}
      @click=${() => Router.go(route.path)}
      >${route.name}</a
    >`;
  }

The content of my router/index.ts is as follows:

import type { Route, RouterLocation } from '@vaadin/router';
import { Router } from '@vaadin/router';
import { routes } from './routes';

const router: Router = new Router();

void router.setRoutes(routes);

export const attachRouter = (outlet: HTMLElement): void => {
  router.setOutlet(outlet);
};

export const getRoutes = (): Route[] => {
  return router.getRoutes();
};

export const getLocation = (): RouterLocation => {
  return router.location;
};

I am bumping into a few issues.

  1. The RouterLocation does not seem to work and to get updated when browsing to a different page. See the following console.log statements. When on https://localhost:9808/about

image

  1. Is it recommenced to use the default Windows location or the Vaadin RouterLocation and why?

I would be super grateful if you could help with that so that I would be able to use the same logic on my application drawer.

Best regards, Alex

EDIT: I suspect that this behaviour has something to do with the lifecycle of the Web Component. Everything got rendered once first and then do not re-updates.

aress31 avatar Sep 18 '20 10:09 aress31

Hi, please consider using urlForName helper as demonstrated in this PR: https://github.com/IBM/pwa-lit-template/pull/64

Is it recommenced to use the default Windows location or the Vaadin RouterLocation and why?

RouterLocation contains information about currently active route, params etc. So In most of cases you probably want to use it, rather than window.location(but nothing should prevent you from using both).

web-padawan avatar Sep 18 '20 13:09 web-padawan

@web-padawan that does not answer my issue with the styling of the link for the current active view.

  • Links for non-active views look like: image

  • Links for the current active view look like: image

So it is all about setting the active CSS class on my link when the current route path matches the current Windows location, however it seems that Vaadin router does not update the location and therefore the comparison class=${route.path === location.pathname ? 'active' : ''} fails.

Any idea?

aress31 avatar Sep 18 '20 13:09 aress31

Hi @aress31, vaadin-router fires a vaadin-router-location-changed event when the location changes, maybe you can update the link style in an event listener? sth like

window.addEventListener(
      "vaadin-router-location-changed",
      updateActiveLinkStyle
);

haijian-vaadin avatar Sep 18 '20 13:09 haijian-vaadin

@haijian-vaadin I think that would do the job, would you by any chance have a minimal example - maybe worth adding to the doc - on how to do it?

aress31 avatar Sep 18 '20 13:09 aress31

@aress31 you have an example here:

http://github.com/IBM/pwa-lit-template/compare/navigation

abdonrd avatar Sep 18 '20 14:09 abdonrd

Thanks for the example @abdonrd however I can see an issue, when clicking on a new link it works fine and update the style but when browsing via the URL to a page nothing happen, there should be some logic with the location somewhere to cover this use case isn't?

Also eslint was not really happy with the code you sent and I had to deactivate a few rules, see:

  firstUpdated(): void {
    attachRouter(this.outlet);
    window.addEventListener(
      'vaadin-router-location-changed',
      (event) => {
        console.log(event);
        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        const { route } = (<CustomEvent>event).detail.location;
        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        this.currentRouteName = route.name;
      }
    );
  }

Could you please advise on how to fix eslint warnings?

Also, a small side comment, but I believe that in the lit documentation states that windows event listeners should be defined in the connectedCallback lifecycle method - please correct me if wrong. Therefore, the pwa-starter-kit should be more something like:

  connectedCallback(): void {
    super.connectedCallback();
    window.addEventListener('scroll', this.onWindowScroll);
    window.addEventListener('scroll', this.routerRestoreScroll);
    window.addEventListener(
      'vaadin-router-location-changed',
      (event) => this.updateCurrentRouteName(<CustomEvent>event)
    );
  }

  disconnectedCallback(): void {
    super.disconnectedCallback();
    window.removeEventListener('scroll', this.onWindowScroll);
    window.removeEventListener(
      'scroll',
      this.routerRestoreScroll
    );
    window.removeEventListener(
      'vaadin-router-location-changed',
      (event) => this.updateCurrentRouteName(<CustomEvent>event)
    );
  }

  firstUpdated(): void {
    attachRouter(this.outlet);
  }

aress31 avatar Sep 18 '20 14:09 aress31

@aress31 mmm it works well for me; whether I change route or enter a route directly.

And about the ESLint, it depends on how you configure your rules.

And about the event listeners, it depends; in this case for the router I prefer to use the firstUpdated().

abdonrd avatar Oct 12 '20 09:10 abdonrd

@aress31 I have the same issue when navigating manually via URL -> how did you solve your problem? Kind regards

klauss194 avatar Nov 14 '23 19:11 klauss194