Show & Hide some elements based on input - radio buttons

What do you mean by this?

Missed that, added

An important property of ReactiveVars — which is sometimes a reason for using one — is that setting the value to the same value as before has no effect; it does not trigger any invalidations. So if one autorun sets a ReactiveVar, and another autorun gets the ReactiveVar, a re-run of the first autorun won’t necessarily trigger the second. By default, only primitive values are compared this way, while calling set on an argument that is an object (not a primitive) always counts as a change. You can configure this behavior using the equalsFunc argument.

Is this needed in this case? I haven’t used it like that so I don’t really know

Well, exactly in this case not.
But if you start it as object, ppl tend to add properties there and use on xyz other places :smiley:

Thanks for the reply @shock! Though I wonder what you mean with this, and what is your suggestion exactly? Can you just mention pls? I don’t expect you to right the whole code though…

In any case, I need to set the helper to show data according to the selected button, which, in turn, necessitates that I create an event object to handle constant tracking and pass it to the helper. Right?? In that case, how would your code differ than that of @benjick’s?

Cheers.

Yes, the approach with helper returning some value and using #if in templase is the right approach.
@benjick also used ‘template’ in helper without definition, but principle was right.
I am not sure if there should be ‘this’ or Template.instance() so I use instance :smiley:
There is no need for break in default
OCD rulezz

Code I would use looks like this if ‘this’ could not be used instead of 'Template.instance()'
I never know which way to use it, always just try

Template.myTemplate.onCreated = function () {
	this.options = new ReactiveVar(null);
}

Template.myTemplate.events({
	'change': function(event, template) {
		switch(event.currentTarget.value) {
			case showToMe:
				template.options.set("toMe")
				break;
			case showByMe:
				template.options.set("byMe")
				break;
			default:
				template.options.set(null)
		}
	}
})

Template.myTemplate.helpers({
	myHelper: function () {
		return Requests.find(Template.instance().options.get());
	}
});
1 Like

OK perfect. Thanks. I’ll try when I get home and return with a comment on how it worked :blush:

Hello there again!

Now I got it to work. Thanks a lot! Though I had to change a few things so I’ll mark them here:

Template.myTemplate.onCreated needs to change to: Template.myTemplate.created

event.currentTarget.value doesn’t get the value of the selected radio button. But this does:

template.find('input:radio[name=myBut]:checked').value

There’s one more issue that I couldn’t figure out. So please help if you can:
Since the reactiveVar is only created on “change” in the event, there is nothing displayed on the page render even if the first radio button is selected (on template markup). Can anybody please point me to how I can render the default case in the first render of the page?

Many thanks!

Template.myTemplate.created is deprecated. You should be using Template.myTemplate.onCreated like you tried originally. However, the syntax you used in your example was incorrect. It should be:

Template.myTemplate.onCreated(function () {
	this.options = new ReactiveVar(null);
});

You could set the initial value of your ReactiveVar to the radio button’s initial value, rather than null.

Hi!

That’s correct! You rule.

I’ve done that exactly, but it didn’t work. I did this:

default: template.showWhat.set({})

But the thing is the whole switch case function runs if there’s a change event - because we declare so. Therefore it doesn’t work… :confused: Where can I initialise the ReactiveVar value without having to rely on a change event on the template?

So, there seem to be a few gaps in information, which is making this hard to understand.

Do you have autopublish included or are you using publish/subscribe - and what/where are your publish and subscribe code?

Your case statement seems syntactically incorrect unless you have declared variables showToMe and showByMe somewhere else. I would have expected to see "showToMe" and "showByMe".

Your template’s helper function will run even before a button is pressed, so it will first be invoked as:

Requests.find(Template.instance().options.get());

so, with options set to {} it will run as:

Requests.find({});

which should return everything (unless there is something awry with your subscription - see earlier pub/sub question).

If you have a minimum reproduction in a repo that would help :smile:

Hello there!
I know what you mean. I write you here below the exact code. I’ve altered the code that @shock have sent. Didn’t note here because I thought it was already conceivable detail:

Template.requestsList.events({
	"change": function(event, template) {
	  var currentUserId = Meteor.userId();
	  var element = template.find('input:radio[name=myBut]:checked').value;
	  switch(element) {
            case "showToMe":
              template.options.set({reqFrom: currentUserId});
              break;
            case "showByMe":
              template.options.set({reqBy: currentUserId});
              break;
            default:
              template.options.set({});
          }
	}
});

So where do you think I do wrong? It’s not showing anything on page render…
Thanks.

To reiterate …

Do you have autopublish included or are you using publish/subscribe - and what/where are your publish and subscribe code?

I’ve published publications on the server/server.js file and subscribed them on client/client.js.

If it was anything to do with pub/sub issue, I don’t think I’d have the button event working at all… I mean it works perfect when one clicks a radio button. Problem is that nothing shows on the page render, before one clicks any radio button. So are you sure the whole function runs before the “click” event is triggered - radio button pressed???

Yes, autopublish was removed long ago.

Is the template you listed originally still correct?

<template name="myTemplate">  
    <div>
      <input type="radio" name="myBut" value="showAll" checked="checked">All
      <input type="radio" name="myBut" value="showToMe">To Me
      <input type="radio" name="myBut" value="showByMe">By Me
    </div>
      {{#each myHelper}}
          {{list-item}}   
      {{/each}}
</template>

I assume the template name is actually “requestsList” to match your events?

Yes, exactly. Sorry I tried to name the markup more semantically to make sense here. Forgot to change…

So, to confirm the running of the helpers when button action is out of the picture, change your helper to:

Template.requestsList.helpers({
  myHelper: function () {
    return [
      {'list-item': 'cat'},
      {'list-item': 'dog'}
    ]
  }
});

So, an array of objects each having a list-item member.

Edit: as I type this I wonder whether you’ve ensured your subscription is ready? The above change makes it guaranteed ready, so if it works (as I expect it to) it may just point to your subscription needing wrapping in an autorun to pick up the ready state when it happens.

Hi @robfallows,

Indeed, I use these helper wrapping my helper in the template.

{{#if isSubReady 'requests'}}
  --previously embedded code--
{{else}}
  loading...
 {{/if}}

And I don’t see loading… So I assume sub is ready. :blush:

This is one of the arillo:flow-router-helpers?

If you check the code for these you will see that the isSubsReady helper is sugar for flow-router’s FlowRouter.subsReady(). If you read the documentation for that you will see that @arunoda wraps this in a Tracker.autorun():

After you’ve registered your subscriptions, you can reactively check for the status of those subscriptions like this:

Tracker.autorun(function() {
  console.log(“Is myPost ready?:”, FlowRouter.subsReady(“myPost”));
  console.log(“Does all subscriptions ready?:”, FlowRouter.subsReady());
});

The point being a subscription can be “ready” (set up and ready to go) even if no data is available. So, in order to ensure that you get to see the data as it becomes available, you still need to wrap the check in an autorun as arunoda recommends.

Incidentally, for v3 of flow-router, arunoda has said that subscription management will be removed:

FlowRouter also has it’s own subscription registration mechanism. We will remove this in version 3.0.

I highly recommend reading the subscription management section of the flow-router repo.

Aha OK, cool. I’m at work now, and will try your previously posted code when I get home.

Thanks a lot for the tips!