loading...
Cover image for Dynamically set default queryParams in ember > v3.6.x

Dynamically set default queryParams in ember > v3.6.x

michalbryxi profile image Michal Bryxí ・2 min read

Imagine you have an app with following route:

https://example.com/calendar

This route can accept optional queryParams from and to that will determine what part of the calendar should be displayed:

https://example.com/calendar?from=2019-09-01&to=2019-09-08

And now imagine that there is a requirement to let the users access the bare URL and display current week.

One option would be to check whether from and to are set, and if not fill those with respective values somewhere inside the code logic.

I am a firm believer of deriving as much state of the app as possible from the URL. So I would suggest: Check whether from and to are set, and if not redirect the app to URL with those queryParams set to respective values. Or in other words: Deriving the state from the outside.

My main reasons on why this is a good idea are:

  • The URL can be bookmarked & shared and every user will see the same data.
  • We have to set the queryParams on one place and every part of the app can to read the values from that place.

I had the redirect approach implemented in my app:

// COMPATIBLE WITH ember v3.4.3

import Route from "@ember/routing/route";
import moment from "moment";

export default Route.extend({
  queryParams: {
    from: { refreshModel: true },
    to: { refreshModel: true },
  },

  beforeModel(transition) {
    let params = transition.queryParams;
    if (!params.from || !params.to) {
      this.replaceWith({
        queryParams: {
          from: moment()
            .startOf("week")
            .format(dateFormat),
          to: moment()
            .endOf("week")
            .format(dateFormat)
        }
      });
    }
  },
});

This stopped working for me while doing an upgrade to ember v3.12.0. Digging through the changelog and pull requests I found out that in ember v3.6.x new RouteInfo objects from and to has been added.

So I made respective changes and now the code looks like:

// COMPATIBLE WITH ember > v3.6.x

import Route from "@ember/routing/route";
import moment from "moment";

export default Route.extend({
  queryParams: {
    from: { refreshModel: true },
    to: { refreshModel: true },
  },

  beforeModel(transition) {
    let params = transition.to.queryParams; // << This line has changed
    if (!params.from || !params.to) {
      this.replaceWith({
        queryParams: {
          from: moment()
            .startOf("week")
            .format(dateFormat),
          to: moment()
            .endOf("week")
            .format(dateFormat)
        }
      });
    }
  },
});

From the wording in the PR I came to a conclusion that I was using a private API of the transition object, which is never a good idea.


Cover photo from Diomari Madulara on unsplash.

Posted on by:

michalbryxi profile

Michal Bryxí

@michalbryxi

Cycle 🚴 , climb 🗻 , run 🏃 , travel 🌍 , enjoy life ♥. IT guy with the need to live fully.

Discussion

pic
Editor guide