Direction-aware transition with Ember Liquid Fire's {{liquid-with}} helper

573 views Asked by At

In my Ember app, I would like to make nice Liquid Fire transitions within the same route when the model of a dynamic route changes. Here's my router:

// app/router.js

Router.map(function() {
    this.route("campaigns", { path: "/" }, function() {
        this.route("campaign", { path: "/campaign/:election_year" });
    });
});

I would like the view to leave the screen to the left when switching to an election_year that is in the future (e.g., from campaign/2008 to campaign/2012) and to the right the other way around.

My first thought was to use use the {{liquid-outlet}} and the toModel function in the app/transitions.js file, but Edward Faulkner (creator of Liquid Fire) says in this thread that

liquid-outlet does not handle model-to-model transitions on the same route

and that I should use {{liquid-with}} instead. However I'm at a loss as to how to handle the directionality, i.e. make the view go left when election_year increases, and go right when it decreases. Any clues?

1

There are 1 answers

3
Ed4 On BEST ANSWER

When using a liquid-with (or liquid-bind) helper, there is not necessarily a route or model involved in the animation, and so constraints like toRoute or toModel do not apply. Instead, you can use toValue which will match against whatever you're passing into the helper.

Assuming you're passing a Campaign model to liquid-with, you could use a rule like this in transitions.js:

this.transition(
  this.toValue(function(newValue, oldValue) {
    return newValue instanceof Campaign &&
           oldValue instanceof Campaign &&
           newValue.electionYear > oldValue.electionYear
  }),
  this.use('toLeft'),
  this.reverse('toRight')
)

Explanation:

We have a constraint, an animation to use when it matches (toLeft), and an animation to use when it matches with "to" and "from" reversed (toRight),

All the rule constraints (including toValue, fromRoute, etc) can accept:

  • simple values like toValue(42) or toRoute('posts') that will be compared with ===
  • regular expressions like toRoute(/unicorn/)
  • functions that test the value, like toValue(n => n > 1).
  • functions that compare the value and the "other value", like

    toValue((newThing, oldThing) => newThing.betterThan(oldThing))
    

The final case is what we're using in the solution above.

(We are continuing to refine these APIs. In this particular case, I think we should add an explicit name for the comparison rule, like this.compareValues(function(oldValue, newValue){...}), instead of just overloading toValue to also do comparison. But this should not affect your solution, as I'm not going to break the existing behavior in the foreseeable future.)