Xyand
Xyand

Reputation: 4488

How to change style of multiple elements efficiently

I have a simple list of images and a button I use to change the size of those images whenever it is clicked. I implemented this behavior in several ways and there are significant performance and behavior (template re-rendering) differences. My question is what is the preferred way to implement this in Meteor?

This is a minimal working example. In reality the images can be better identified and the size change can be triggered from different events.

Solution 1 (The demo way = slow/re-render):

Template.controls.events = {
    "click #change_size": function() {
        Session.set("height", "20px");
    }
};

<template name="image">
    <img src="img.jpg" style="height: {{height}}"/>
</template>

Template.image.height = function() {
    return Session.get("height");
};

Solution 2 (jQuery + state):

Template.controls.events = {
    "click #change_size": function() {
        Session.set("height", "20px");
    }
};

<template name="image">
    <img src="img.jpg"/>
</template>

Meteor.autorun(function() {
    $("img").css({height: Session.get("height")});
})

Solution 3 (jQuery):

Template.controls.events = {
    "click #change_size": function() {
        $("img").css({height: "20px"});
    }
};

<template name="image">
    <img src="img.jpg"/>
</template>

Solution 4 (Reactive parent):

Template.controls.events = {
    "click #change_size": function() {
        Session.set("height", "20px");
    }
};

<template name="image_set">
    {{#each image_set}}
    <img src="img.jpg" style="height: {{../height}}"/>
    {{/each}}
</template>

Template.image_set.height = function() {
    return Session.get("height");
};

Solution 5: ???

Upvotes: 0

Views: 430

Answers (3)

Xyand
Xyand

Reputation: 4488

Solution #5:

I don't know if it is considered a good meteor practice, or if there is such a thing as meteor best practices. The solution is to use templated embedded css rules. The following lines seem to do the trick:

Template.controls.events = {
    "click #change_size": function() {
        Session.set("height", "20px");
    }
};

<img src="img1.jpg" class="my_class" />
...
<img src="img1000.jpg" class="my_class" />

<template name="css">
<style media="screen" type="text/css">
img.my_class {
  height: {{height}};
}    
</template>

Template.css.height = function() {
    return Session.get("height");
};

Pros:

  • no jQuery
  • single template rendering
  • all styling is done by the optimized browser code

Cons?

Upvotes: 0

handmade
handmade

Reputation: 201

#1 and #2 mix jQuery dom manipulation and Sessions. I would avoid them for performance and coherence reasons. if #3 and #4 have comparable performance, #4 is the way to go, since that Session allow you to easily "plug" other event handlers if needed.

If possibile, i'd rather suggest to manipulate the class of the wrapper and set the image height with a css rule.

Upvotes: 0

Rahul
Rahul

Reputation: 12231

I would go with #1 or #3 depending on how flexible the application needs to be, or whether I'm porting from a jQuery-based app to Meteor, etc. I prefer to avoid Meteor.autorun if I have an alternative that already uses an inbuilt reactive variable like Session, it feels cleaner and more intentional. Your fourth solution actually solves a different problem: it sets height on multiple images at once. That may not be what you want.

Overall I think #1 is the most Meteoric, given that it's in the docs and it uses the default reactivity of Session in cooperation with Template.

Upvotes: 1

Related Questions