Picture of Henrik Aabom
Handlebars problems
by Henrik Aabom - Friday, 1 April 2016, 12:14 PM
 

Hi all

Maybe someone can point me in the right direction here.

I've created a new component, which has a button that shows some text and a button that hides it again.

The component works fine and it imports as it should in the AT.

However if I try put more than one of this component on a page, it is only the first one that works. It is always, the first one of the components that works and the second, third, fourth, and so on, never work.

I've started out with the text-component and added code to it.

Is it because I'm using jQuery code directly in the .js file of the component? 

Can someone point me in the right direction? What do I have to learn in order to understand, why it doesn't work? Should I delete the Javacode I have written already and use Handlebars instead? Or is it something else?

Any help will be greatly appreciated.
Thanks!

Henrik Aabom

 

My .hbs-code:

<div class="text-inner component-inner" role="region" aria-label="{{_globals._components._text.ariaRegion}}">
{{> component this}}

<div id="moreTxt" class="mynewdiv">
<p>{{{moreText}}}</p>
<button id="btnHide" type="button">{{{lessText_btn}}}</button>
</div>
<div id="lessTxt"><button id="btnShow" type="button">{{{moreText_btn}}}</button></div>
</div>

 

My .js-code:

In the postRender: function() I have put the code:

$("#moreTxt").hide();

 

And in the inview: function I have put:

$("#btnHide").click(function(){
$("#moreTxt").hide(1000);
$("#lessTxt").show(1000);
});
$("#btnShow").click(function(){
$("#moreTxt").show(1000);
$("#lessTxt").hide(1000);
});

Picture of Matt Leathes
Re: Handlebars problems
by Matt Leathes - Friday, 1 April 2016, 1:59 PM
 

It's the jquery selector you're using - the way it's written it will match all elements on the page with id moreTxt - and, if you look at the JQuery ID selector docs you'll see it says

If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM

It does also go on to recommend that you shouldn't have multiple elements with the same ID on the page anyway; we would normally favour using classes over IDs for something like this - for this exact reason.

Anyway, to correct the selector you just need to give it some scope to search within - this.$el('#moreTxt') should do the trick. Or you could do $('#moreTxt', this.$el). I personally think the former is clearer.

Same thing applies to your other JQuery selectors.

Have a look at how the inline transcript is done in the contrib-media component - that's basically doing the same thing as you want to do. It also demonstrates using the Backbone View events hash to handle the button click event - these are a great feature of Backbone Views as they will handle the setting the right 'lexical scope' of this for you - as well as automatically removing the handler when the View is destroyed.

 

Picture of Henrik Aabom
Re: Handlebars problems
by Henrik Aabom - Monday, 4 April 2016, 11:46 AM
 

Thanks Matt

Once again you have the answers to everything ;)

However, it didn't work for me to put in this.$el anywhere. But I found the solution by looking in the media component, as you suggested.

And you were right, the problem was that I didn't set the right scope.

The event hash did the trick! 

 

For anyone who might have a similar problem here is the working code:

From the .js code:

events: {
"click .btnShow": "showHide_text"
},

showHide_text: function(event){
var $moretext = this.$(".moreTxt");
var $lessText = this.$(".lessText");
var $button = this.$(".btnShow");

if ($moretext.hasClass("isOpen")) {
$moretext.hide(1000);
$lessText.show(1000);
$moretext.removeClass("isOpen");
}
else{
$moretext.show(1000);
$lessText.hide(1000);
$moretext.addClass("isOpen");
}
},

 

in the postRender: function() I still have:

$(".moreTxt").hide();

 

and from the .hbs-code:

<div class="text-inner component-inner" role="region" aria-label="{{_globals._components._text.ariaRegion}}">
{{> component this}}

<div class="moreTxt">
<p>{{{moreText}}}</p>
<button class="btnShow button" role="button">{{{lessText_btn}}}</button>
</div>

<div class="lessText">
<button class="btnShow button" role="button">{{{moreText_btn}}}</button>
</div>

</div>