3

I am trying to set the first picture as the "item active" i an Bootstrap Carousel. So, is there a way to make the first element from an collection to be presented different from the rest?

      {{#each pictures}}
        {{#if @first}}
              <div class="item active">
                 <img src="/pictures/{{fileName}}" alt="" />
            </div>
       {{else}}
          <div class="item">
             <img src="/pictures/{{fileName}}" alt="" />
          </div>
       {{/if}}
     {{/each}}

The rendered page only display the content in the {{else}} statement. Have tried using {{if @first}}, but it does not work for me.

Keith Dawson
  • 1,475
  • 16
  • 27
Hans-Olav
  • 33
  • 4

2 Answers2

8

This is pretty similar to the problem of needing an index in your template. You need to map over pictures and mark the one you need treated differently. For example:

Template.myPictures.helpers({
  pictures: function() {
    return Pictures.find().map(function(picture, index) {
      if (index === 0)
        picture.isFirst = true;

      return picture;
    });
  }
});

You can then use isFirst in your template like this:

{{#each pictures}}
  {{#if isFirst}}
    <div class="item active">
      <img src="/pictures/{{fileName}}" alt="" />
    </div>
  {{else}}
    <div class="item">
      <img src="/pictures/{{fileName}}" alt="" />
    </div>
  {{/if}}
{{/each}}

Note that CoffeeScript's @ doesn't work in templates. To learn more about template contexts see this.

Community
  • 1
  • 1
David Weldon
  • 63,632
  • 11
  • 148
  • 146
  • Good idea! What happens when Bootstrap changes the active item and then the cursor updates? Does spacebars respect the change? – Neil Aug 13 '14 at 18:15
  • I *think* the first item would me marked as active again. That would not be true with a regular cursor but because we are using `map` I'm not sure since blaze recently changed how classes are preserved. You'd need to try it and see what happens. If you could catch the event that changes which picture is active, you could change some internal state and then use that state in your map. This gets tricky when pictures could be removed. You'd need to think about all cases and clearly define what the behavior would be. – David Weldon Aug 13 '14 at 18:37
2

It's not exactly what you were asking but you could make the first item active using jQuery in the rendered callback.

Template.myPictures.rendered = function () {
  this.$('.item').first().addClass('active');
};
Neil
  • 2,137
  • 16
  • 24
  • Yep, this is probably also good, provided the pictures are actually ready when the template renders (e.g. a `waitOn` is used). – David Weldon Aug 13 '14 at 21:22
  • This solution also worked. Got so focused on the handlebars that I didn't think of any other solution.. Thanks! – Hans-Olav Aug 14 '14 at 06:12