Meteor ignoring 'selected' attribute on <option> on <select multi> - meteor

I am trying to use a multi select box in meteor and have some of the options be marked with selected based on info from the db for use with slectize.js. however it seems like meteor when building its DOM tree ignores the selected property.
<label>User</label>
<select id="customer_user_id" name="user_id" class="form-control input-sm" multiple>
{{#each users}}
{{#if inList _id ../customer_user_id}}
<option value="{{_id}}" selected>{{full_name}}</option>
{{else}}
<option value="{{_id}}">{{full_name}}</option>
{{/if}}
{{/each}}
</select>
and the helper
Handlebars.registerHelper("inList", function (val, list) {
console.log(list.indexOf(val) > -1)
console.log(list)
console.log(val)
return list.indexOf(val) > -1;
});
i see that the condition is true but there is no options with the selected property
I have been breaking my head on this for more then 24 hours now
I have also tried this method with the same result
<label>User</label>
<select id="customer_user_id" name="user_id" class="form-control input-sm" multiple>
{{#each users}}
<option value="{{_id}}" {{selected _id ../customer_user_id "selected"}}>{{full_name}}</option>
{{/each}}
</select>
with this helper
Handlebars.registerHelper("selected", function (val1, val2, string) {
if (val1 === val2) {
return string;
}
});

Try using selected="selected" instead of just selected:
<option value="{{_id}}" selected="selected">{{full_name}}</option>

Related

Initiate a template iteration in Meteor

Rather than loading a new template, is there a way to force Meteor to initiate an iteration (using {{#each}}) of an array in Meteor? For example, if the user selects a value in a pull down selector, to then initiate Meteor to iterate through an array within that template to populate another multiple selector list rather than load a whole new template with the new selector list.
Let's say this is within a template:
.
.
.
<form class="input-field col s6 card-selector">
<select multiple">
<option value="" disabled selected>Select Students</option>
{{#each StudentList1}}
<option value= '{{FullName}}'>{{formatName FullName}} ({{Level}}) {{RoomWk1}}</option>
{{/each}}
</select>
</form>
.
.
.
When a user selects a value in a different selector in that template:
<select class="week-selector">
<option value="" disabled selected>Week</option>
<option value="Week1">Week 1</option>
<option value="Week2">Week 2</option>
<option value="Week3">Week 3</option>
<option value="Week4">Week 4</option>
<option value="Week5">Week 5</option>
</select>
it will force a reiteration of the first #each to:
<form class="input-field col s6 card-selector">
<select multiple">
<option value="" disabled selected>Select Students</option>
{{#each StudentList1}}
<option value= '{{FullName}}'>{{formatName FullName}} ({{Level}}) {{RoomWk2}}</option>
{{/each}}
</select>
</form>
It would be more efficient than loading a new template that's the same except for the multi selector values.
Sessions are reactive and you can achieve this by using sessions (check if you have session package).
//we don't want the session value from the previous search/events
Template.templateName.onRendered(function(){
Session.set('sessionName', undefined);
});
//I'd probably use onDestroyed instead of onRendered
Template.templateName.onDestroyed(function(){
Session.set('sessionName', undefined);
});
//template events
'change .week-selector': function(){
var selected = $('.week-selector').find(":selected").text();
Session.set('sessionName', selected)
}
//template helper
StudentList1: function(){
var session = Session.get('sessionName');
if(session !== undefined){
//return some documents using the session value in your find()
} else {
//return documents without session value
}
}
EDIT: I found .text() of the selected option in the event but you are free to return value or do whatever you want with the found value/text.

Meteor Dropdown list get and set

What is the best way to get and select values from a dropdown list (and also in radio) in Meteor.
I have created a helper:
Template.categories.helpers({
categories: ["facebook", "news", "tv", "tweets"]
});
and in html
...
<select class="form-control" id="category">
{{> categories}}
</select>
...
<template name="categories">
<option disabled="disabled" selected="selected">Please Select</option>
{{#each categories}}
<option value="{{this}}">{{this}}</option>
{{/each}}
</template>
In case of edit, I would like to evaluate it with value coming from database (e.g. news) to be selected.
Thanks in advance.
Template HTML:
<select id="category-select">
<option disabled="disabled" selected="selected">Please Select</option>
{{#each categories}}
<option value="{{this}}">{{this}}</option>
{{/each}}
</select>
Template js:
Template.categories.helpers({
categories: function(){
return ["facebook", "news", "tv", "tweets"]
}
});
Template.categories.events({
"change #category-select": function (event, template) {
var category = $(event.currentTarget).val();
console.log("category : " + category);
// additional code to do what you want with the category
}
});
Template.categories.helpers({
categories: function(){
return ["facebook", "news", "tv", "tweets"]
}
});
And you should consider changing template name and helper, they shouldn't be the same.

Meteor each loop data not displaying

In each loop data is not displaying.value="{{param_type}}" not displaying.Please help me.
{{ #each api_method_param_data }}
<select id="param_type">
{{#each dropdown}}
{{#if isSelected this param_type}}
<option value="{{param_type}}" selected="selected"> {{this}} </option>
{{else}}
<option value="{{param_type}}" > {{this}} </option>
{{/if}}
{{/each}}
</select>
{{/each}}
This is the helper function
Template.apimethodchange.isSelected = function(fooToCheck, recordFoo)
{
var checkrec = "";
for(var i=0;i<recordFoo.length;i++)
{
checkrec = checkrec + recordFoo[i];
}
console.log(checkrec + fooToCheck);
return (fooToCheck == checkrec);
};
Template.apimethodchange.dropdown = ["string","array","int","boolean","double","struct"];
Try with ../ to access parent context
<option value="{{../param_type}}" selected="selected"> {{this}} </option>

How do I indicate 'checked' or 'selected' state for input controls in Meteor (with spacebars templates)?

So I'm trying to be efficient and clean in my Spacebars templates as I work with Meteor. But I'm stumped by the way in which checkboxes and select options are to be dealt with. Suppose I want to have a checkbox set as checked or not depending on a flag that is in a document in one of my collections. I don't appear to be able to do the following:
<input type='checkbox' id='item-{{this.item_id}}' {{#if checked}}checked{{/if}} />
When I try this, I get the following error:
A template tag of type BLOCKOPEN is not allowed here.
If I try the following options, though, they all result in the checkbox being checked even when the flag is false:
<input type='checkbox' id='item-{{this.item_id}}' checked='{{#if checked}}true{{/if}}' />
<input type='checkbox' id='item-{{this.item_id}}' checked='{{#if checked}}true{{else}}false{{/if}}' />
I have the same trouble with selected in my select options, so I end up doing something like the following to get around it, which seems verbose and error-prone:
<select id='option-{{this.item_id}}'>
{{#if option_60}}
<option value='60' selected>1 hour</option>
{{else}}
<option value='60'>1 hour</option>
{{/if}}
{{#if option_90}}
<option value='90' selected>90 mins</option>
{{else}}
<option value='90'>90 mins</option>
{{/if}}
{{#if option_120}}
<option value='120' selected>2 hours</option>
{{else}}
<option value='120'>2 hours</option>
{{/if}}
</select>
You can use non-block helpers for placing such arguments:
UI.registerHelper('checkedIf', function(val) {
return val ? 'checked' : '';
});
<input type="checkbox" {{checkedIf checked}}>
Here is an example of the code I use to solve this problem, this should be pretty straightforward.
JS
Template.myTemplate.helpers({
checked:function(){
// assumes that this.checked is the flag in your collection
return this.checked?"checked":"";
},
options:function(){
// store options in a helper to iterate over in the template
// could even use http://momentjs.com/docs/#/durations/humanize/ in this case ?
return [{
value:60,
text:"1 hour"
},{
value:90,
text:"90 mins"
},{
value:120,
text:"2 hours"
}];
},
selected:function(value){
// compare the current option value (this.value) with the parameter
// the parameter is the value from the collection in this case
return this.value==value?"selected":"";
}
});
Template.parent.helpers({
dataContext:function(){
// dummy data, should come from a collection in a real application
return {
checked:true,
value:90
};
}
});
HTML
<template name="myTemplate">
<input type="checkbox" {{checked}}>
<select>
{{#each options}}
{{! ../ syntax is used to access the parent data context which is the collection}}
<option value="{{value}}" {{selected ../value}}>{{text}}</option>
{{/each}}
</select>
</template>
<template name="parent">
{{> myTemplate dataContext}}
</template>
EDIT : using universal helpers as Hubert OG hinted at :
JS
Template.registerHelper("checkedIf",function(value){
return value?"checked":"";
});
Template.registerHelper("selectedIfEquals",function(left,right){
return left==right?"selected":"";
});
HTML
<template name="myTemplate">
<input type="checkbox" {{checkedIf checked}}>
<select>
{{#each options}}
<option value="{{value}}" {{selectedIfEquals value ../value}}>{{text}}</option>
{{/each}}
</select>
</template>
The best, most efficient and effective way to accomplish this is to setup global template helpers, one each for determining checked and selected values. For documentation on creating global template helpers, see this documentation.
For checked, I suggest implementing it in this way:
Template.registerHelper('isChecked', function(someValue) {
return someValue ? 'checked' : '';
});
For selected, I suggest implementing it in this way:
Template.registerHelper('isSelected', function(someValue) {
return someValue ? 'selected' : '';
});
With these two global template helpers implemented, you can use them in any of your templates within your application like this:
<template name="someTemplate">
<input type="checkbox" {{isChecked someValue}}>
<select>
{{#each someOptions}}
<option {{isSelected someValue}}>{{someDisplayValue}}</option>
{{/each}}
</select>
</template>

Setting the selected value of a Select element in Handlebars

I have a handlebars template that I am embedding in my html page. There is a select element with all of the available options already rendered. How can I set the selected value of the select list when I render my template?
<script id="my-template" type="text/x-handlebars-template">
<div id="my-modal">
<form action="/TestAction" method="post">
<input id="MyId" name="MyId" type="hidden" value="{{MyId}}" />
<label for="Test">Test: (optional)</label>
<select id="Test" name="Test">
<option value="">-- Choose Test --</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</form>
</div>
</script>
If you don't want to build out the option as part of the helper, you can use a combination of a small custom handlebars helper and parent context, denoted using the ../ syntax:
First write the helper:
Handlebars.registerHelper('selected', function(option, value){
if (option === value) {
return ' selected';
} else {
return ''
}
});
And then in your template you call your helper and pass in the parent context inside the each loop to check for selectedState
{{#each states}}
<option value="{{this}}" {{selected this ../selectedState}}>{{this}}</option>
{{/each}}
I took the {{#each}} helper as inspiration, and wrote a custom helper that does the same thing: loops over a list, and continually appends the contents of the arguments to an output string. (From here: Handlebars block helpers)
In this case, I'm not passing in a chunk of template HTML to serve as the function's options parameter, like you would when using {{#each}}. Instead I am just building up the <option>
tags by brute force, and testing every iteration of the context list. Lastly, I return a big long string of <option></option> tags, and hopefully one of them has selected="selected".
The function:
Handlebars.registerHelper('options_selected', function(context, test) {
var ret = '';
for (var i = 0, len = context.length; i < len; i++) {
var option = '<option value="' + context[i]+'"';
if (test.toLowerCase() == context[i].toLowerCase()) {
option += ' selected="selected"';
}
option += '>'+ Handlebars.Utils.escapeExpression(context[i]) + '</option>';
ret += option;
}
return new Handlebars.SafeString(ret);
});
The tag in use:
<script id="form-state" type="text/x-handlebars-template">
<select name="state">
{{{options_selected states selectedState}}}
</select>
</script>
Please suggest any edits that would improve this, thanks!
You can use values straight in the Handlebars template like so.
Handlebars Template
<select id="distance">
<option value="15" {{#if (isEqual 15 distance)}} selected {{/if}}>15</option>
<option value="25" {{#if (isEqual 25 distance)}} selected {{/if}}>25</option>
<option value="50" {{#if (isEqual 50 distance)}} selected {{/if}}>50</option>
<option value="100" {{#if (isEqual 100 distance)}} selected {{/if}}>100</option>
<option value="300" {{#if (isEqual 300 distance)}} selected {{/if}}>300</option>
</select>
Handlebars Helper
define(['hbs/handlebars'], function (Handlebars) {
'use strict';
Handlebars.registerHelper('isEqual', function (expectedValue, value) {
return value === expectedValue;
});
});
Here is a solution (built over EmberJS to ease the JS part)
I refactored your sample a little, to have objects for proposed values, which can by the way carry the selected attribute...
The template part:
<script type="text/x-handlebars" data-template-name="my-template">
<div id="my-modal">
<form action="/TestAction" method="post">
<input id="MyId" name="MyId" type="hidden" value="{{MyId}}" />
<label for="Test">Test: (optional)</label>
<select id="Test" name="Test">
<option value="">-- Choose Test --</option>
{{#each values}}
<option {{bindAttr value="id" selected="selected"}}>{{label}}</option>
{{/each}}
</select>
</form>
</div>
</script>
The JS part:
App.MyView = Ember.View.extend
templateName: 'my-template'
MyId: 42
values: [{
id: 1,
label: '1'
}, {
id: 2,
label: '2'
}, {
id: 3,
label: '3',
selected: true
}, {
id: 4,
label: '4'
}]
You can try it # http://jsfiddle.net/MikeAski/uRUc3/
I had same problem.
$('select').val(value);
This is how I solved it, I set the desired value with jQuery after rendering the template. Was surprisingly easy. (Maybe its also a way to keep the templates logicless)

Resources