Detect changes to query parameters on same route

I’m building a page with only a couple element to trigger filter/load data. To be more specific, I have a list of records that can have one of 3 different “status” values, plus dates, etc. I want to tab each “status”, then provide additional field fields for refined filtering. This is all within the same view. In doing so, I’d like to write the tab and other filters to the url/route querystring. The problem is that the activate() method is only called once, and I’m wondering how to accomplish this while still maintaining the flexibility of using the query parameters to drive the tab/filters, which is critical for first loading or full page reloading.

This is wrong approach, but you see what I mean:

      <ul class="nav nav-tabs">
        <li class="nav-item">
          <a class="nav-link ${(filter.status === 'PRIVATE') ? 'active':''}" click.delegate="setStatus('PRIVATE')"  href=""><i class="bi bi-file-earmark-lock"></i>&nbsp;Private/Draft</a>
        </li>
        <li class="nav-item">
          <a class="nav-link ${(filter.status === 'PUBLIC') ? 'active':''}" click.delegate="setStatus('PUBLIC')"  href=""><i class="bi bi-calendar-check"></i>&nbsp;Published</a>
        </li>
        <li class="nav-item">
          <a class="nav-link ${(filter.status === 'DELETED') ? 'active':''}" click.delegate="setStatus('DELETED')"  href=""><i class="bi bi-trash"></i>&nbsp;Deleted</a>
        </li>
      </ul>
    constructor(private router: Router, private postService: PostService) {

    }

    activate(params: any, routeConfig: RouteConfig): Promise<any> {
        this.posts = [];
        this.filter = {
            status: params.status || StatusType.PRIVATE,
            text: params.text,
            startDate: params.startDate,
            endDate: params.endDate,
            beginIndex: params.beginIndex || null
        }
        return this.loadMore();
    }

    setStatus(status: StatusType) {
        if (status !== this.filter.status) {
            this.filter.status = status;
            this.loadNew();
        }
    }

    loadNew() {
        this.filter.beginIndex = null;
        this.posts = [];
        this.loadMore();
    }

    loadMore() {
        return this.doFilter().then((posts) => this.posts.push(...posts)).catch(console.log)
    }

    doFilter(): Promise<PostClientModel[]> {
        return this.postService.search(this.filter);
    }

What’s the solution here? Just use the injected router to navigate when a status/tab and filter changes, even though the navigation won’t actually do anything, it will set the query parameters. Then, just continue with loading more data. I mean, I just want the url to reflect the current data filter state so it can be restored from the url/link.

Maybe activate() is not being called because the default activationStrategy for a route is noChange, which reuses the view model, without invoking lifecycle hooks.
You could try to set the following parameter on your route definition:

{
...
activationStrategy: 'invoke-lifecycle',
...
}

Hope this helps.

Yes, that helped. I’m playing around with this:

  import {activationStrategy} from 'aurelia-router';
  
  export class Controller {
    determineActivationStrategy() {
      return activationStrategy.replace;
    }
  }

I then simply navigate using the route + query params. Seems to work well, and with full page reload.

Thanks!

Glad you worked it out!.

1 Like