Carousel with Liquid Fire?


#1

I was looking around with carousel implementations for Ember and was not happy with any of them, and my use case is pretty simple, so I thought it would be simple enough to roll my own using Liquid Fire, except… well, I’m not sure how to get started.

I basically have four divs that I want to be able to cycle through with a navigate-left and navigate-right button, like you see in most carousels. So at the very higest level, it looks something like:

<div class="carousel">
  <div class="tab-1">A</div>
  <div class="tab-2">B</div>
  <div class="tab-3">C</div>
  <div class="tab-4">D</div>
</div>
<button onclick={{action "navLeft"}}>Left</button>
<button onclick={{action "navRight"}}>Right</button>

I thought about using {{liquid-if}}, but that only supports two states (true/false). Would it be possible to chain liquid-ifs? I tried something like this:

{{#liquid-if (eq tab 1) class="tab-1"}}
  <div class="tab-1">A</div>
{{else}} 
  {{#liquid-if (eq tab 2) class="tab-2"}}
    <div class="tab-2">B</div>
  {{else}}
    {{#liquid-if (eq tab 3) class="tab-3"}}
      <div class="tab-3">C</div>
    {{else}}
      <div class="tab-4">D</div>
    {{/liquid-if}}
  {{/liquid-if}}
{{/liquid-if}}

But that doesn’t seem to work right. Going right works (ie, div scrolls to the left), but going left doesn’t in that the div still scrolls to the left.

So is there a way to make this work? Would making each div as its own route make things simpler? (In my use case, this is possible).


#2

Answering my own question here. I finally got it to work, but I don’t know how good the implementation is. I ended up using {{liquid-bind}}

{{#liquid-bind liquidBindValue class="liquid-carousel" as |current|}}
  {{#if (eq current.currentTab 1)}}
    <div class="tab-1">A</div>
  {{else if (eq current.currentTab 2)}}
    <div class="tab-2">B</div>
  {{else if (eq current.currentTab 3)}}
    <div class="tab-3">C</div>
  {{else}}
    <div class="tab-4">D</div>
  {{/if}}
{{/liquid-bind}}
<button onclick={{action "navLeft"}}>Left</button>
<button onclick={{action "navRight"}}>Right</button>

liquidBindValue is a simple computed object that contains the current tab ID as well as the click direction

{ currentTab: <currentTabId>, lastDirection: [left|right] }

And my app/transitions.js looks like:

export default function() {
  this.transition(
    this.hasClass('liquid-carousel'),
    this.toValue(function(newValue) {
      return (newValue.lastDirection === 'right');
    }),
    this.use('toLeft')
  );
  this.transition(
    this.hasClass('liquid-carousel'),
    this.toValue(function(newValue) {
      return (newValue.lastDirection === 'left');
    }),
    this.use('toRight')
  );
}

I was stuck for awhile trying to make just one transition object that contains both toLeft and toRight (via this.reverse()), but I couldn’t get it to work right, so I’m using two separate transitions. I don’t know if this causes any issues, but from playing around with the above code, it seems to work just fine.

I don’t know if the above can be generalized to accept N number of carousel items, but for my use case, it’s a non-issue since I’ll ever only have 4-5 items.


#3

I’m a contributor on https://github.com/selvagsz/ember-carousel and would definitely take a PR like that if you’re up to it.