I can I update a div using JavaScript with no problem. For example, the initial values for both divs are shown on the image on the left, and the values after clicking on the test button are shown on the right.
when I click the test button then the counter is increased by 1 and the values for the divs are changed like this:
var ela = document.getElementById("a");
var elb = document.getElementById("b");
$("#" + ela.id).html("new value " + ela.id + " ");
$("#" + elb.id).html("new value " + elb.id + " ");
So far so good, but now I would like to change the order of the divs: when the counter is even I want div a = yellow to be at the top (div b = grey at the bottom), and the other way around when the counter is uneven.
For simplicity in the example I use 2 small arrays for each of the possible orders (a,b) and (b,a) and a helper 'order' will return 1 of the 2 cases depending on the counter value (x%2 is zero or not)
Unfortunately, the result is not what I want and expected. The divs are changing position correctly, but their text is not. After the first click the counter goes from 5 to 6, so the yellow div is moving from bottom to top, but the text inside the divs is wrong, I expect 'new value a' in the yellow div that moved up, but I get 'new value b a' instead (same for other div the other way around)
Also when I inspect the divs in the console output I'm seeing strange results, Meteor seems to be confused about div ids? see the below image, the first div is both a and b, and yellow and grey at the same time ...
Does anybody know why this is? And how can I fix it?
I know I can just use helpers to get the correct text in the correct div. But my end goal is not to change the text inside divs, but instead I want to create a slider using nouislider like this:
var noUiSlider = require('nouislider');
var sliderHtmlElement = document.getElementById("a");
var options = {
start: [0, 100],
range: {
'min': [0],
'max': [100]
}
};
noUiSlider.create(sliderHtmlElement, options);
My complete test code:
<template name="MyTemplate">
{{x}}
<br>
<br>
{{#each order}}
<div class="{{label}}" id="{{label}}"
style="background-color: {{color}};">
start value {{label}}
</div>
<br>
{{/each}}
<button class="test">test</button>
</template>
var order1;
var order2;
Template.MyTemplate.onCreated(function() {
Session.set("x", 5);
var or0 = [];
or0["label"] = "a";
or0["color"] = "yellow";
var or1 = [];
or1["label"] = "b";
or1["color"] = "grey";
order1 = [];
order1[0] = or0;
order1[1] = or1;
order2 = [];
order2[0] = or1;
order2[1] = or0;
});
Template.MyTemplate.events({
'click .test': function(event) {
var varx = Session.get("x") + 1;
Session.set("x", varx);
createSliders();
}
});
Template.MyTemplate.helpers({
x: function() {
return Session.get("x");
},
order: function() {
if (Session.get("x") % 2 === 0) {
return order1;
} else {
return order2;
}
}
});
function createSliders() {
var ela = document.getElementById("a");
var elb = document.getElementById("b");
console.log(ela);
console.log(elb);
$("#" + ela.id).html("new value " + ela.id + " ");
$("#" + elb.id).html("new value " + elb.id + " ");
}
With Blaze you have to explicitly import the
.css
file as well in order to get the styles applied:Then you can easily use the Template's builtin jQuery to get a target div where nouislider will render.
Consider the following template:
Now let's render a new nouislider into the div with id
range
by clicking the button:Now you could also easily add some reactive data here (but avoid
Session
):... and connect it with some data. The
noUiSlider
allows you to hook into it's update event, from where you can pass the values into the state:Render the value into the template using a helper:
Import your own
.css
files to statically style the slider like so:or style it dynamically using jQuery's css.
UPDATE: Correct rendering on updated display list
The issue you described is correct and can be reproduced. However it can also be prevented, using
Template.onRendered
to control the point when rendering may occur.I extended the Template to the following code:
Now look inside the target div, which previously had only an id assigned. Now there is a
{{#if ready}}
flag and a function, call to{{slider this}}
.Now in order to render only when the DOM has initially been rendered, we need
Template.onRendered
:and add it to the (updated) helpers:
Now we have some more issues here that need to be resolved. We only want to render if the switch changes but not if the values update. But we need the latest values in order to re-assign them as start position in the next render (otherwise the sliders would be set with the start values 0,100).
To do that we change the
onCreated
code a bit:Now if we press the switch button want a) delete all current sliders with their events etc. and b) update the
sliders
data to our new (reversed) state:Because we have multiple slider values to be updated separately, we also need to change some code in the
createSlider
function:By using this approach you some advantages and some disadvantages.
autorun
required