vaadin / router

Small and powerful client-side router for Web Components. Framework-agnostic.
https://vaadin.com/router
Apache License 2.0
406 stars 49 forks source link

[WebComponent and RouterLocation] General Questions #480

Open aress31 opened 3 years ago

aress31 commented 3 years ago

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.

web-padawan commented 3 years ago

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).

aress31 commented 3 years ago

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

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?

haijian-vaadin commented 3 years ago

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
);
aress31 commented 3 years ago

@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?

abdonrd commented 3 years ago

@aress31 you have an example here:

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

aress31 commented 3 years ago

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);
  }
abdonrd commented 3 years ago

@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().

klauss194 commented 7 months ago

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