Select2 options in MeteorJS - javascript

I am trying to instantiate a multi-select box with Meteor JS and Select2. My html resides in a template as follows:
<template name="selectbox">
<select id="testbox">
<option value="AL">Alabama</option>
<option value="AL">Washington</option>
</select>
</template>
Within my client js I have the following code:
Template.selectbox.rendered = function(){
var options = { allowClear : true, multiple : true }
$("#testbox").select2(options);
};
Unfortunately my browser's console produces the following error:
Exception from Deps afterFlush function: Error: Option 'multiple' is not allowed for Select2 when attached to a <select> element.
I have also tried placing the following code directly in my client js file (as well as within Template.selectbox.create):
$(document).ready(function(){
var options = { allowClear : true, multiple : true }
$("#testbox").select2(options);
});
Unfortunately I receive the same error. The peculiar thing is I receive no error if my options are simply:
var options = { allowClear : true, placeholder : 'test' }
Neither option appears to take affect. However, The rendering of the select box is that of selct2.
Any idea what could be the issue? Thanks in advanced.

See how the example on select2 website is made. According to that code, you should add multiple attribute to the select tag, not to js method parameters.
So in your template replace <select id="testbox"> with <select multiple id="testbox">.

Related

Using Handlebars.js to iterate over a list of names

I have a Bootstrap select dropdown, and I'm attempting to use Handlebars JS to output the desired options into my selection, but they aren't appearing. I've read some examples here so not sure what is stopping my code from correctly rendering, any pointers would be appreciated.
HTML:
<select class="custom-select" id="inputGroupSelect01" onChange="takeSelectedSourceValue(this);">
<option id="source-language" value="" selected disabled>Auto</option>
<div id="myForm"></div>
<script type="text/handlebar-template" id="selectPersonTemplate">
{{#each people}}
<option value="{{valueLang}}">{{htmlLang}}</option>
{{/each}}
</select>
</script>
<script src="https://twitter.github.io/typeahead.js/js/handlebars.js"></script>
JS:
$(function () {
// Define an array of people.
var people = [
{ valueLang: 'DE', htmlLang: 'DE' },
{ valueLang: 'FR', htmlLang: 'FR' },
{ valueLang: 'IT', htmlLang: 'IT' },
{ valueLang: 'ES', htmlLang: 'ES' },
{ valueLang: 'SV', htmlLang: 'SV' },
{ valueLang: 'DA', htmlLang: 'DA' }
];
// Get the text for the Handlebars template from the script element.
var templateText = $("#selectPersonTemplate").html();
// Compile the Handlebars template.
var selectPersonTemplate = Handlebars.compile(templateText);
// Evaluate the template with an array of people.
var html = selectPersonTemplate({ people: people });
// Take the HTML that was created with the Handlebars template and
// set the HTML in the myForm div element.
$("#myForm").html(html);
});
There are a few things wrong with your HTML.
First, your closing select tag, </select> is within your template script tag.
What is within your script tag is ignored by the HTML parser because you have defined the script as type="text/handlebar-template". Therefore, the parser does not see a closing select tag.
Second, <div> elements are not valid children of select, <select>, elements.
I am not sure if all browsers handle this invalid tag the same way, but I am trying it using Chrome and it seems that Chrome is completely ignoring the <div id="myForm"></div> when rendering. So there is no element to which to add the html produced by your template function. The html value should be appended to the <select>.
I would advise taking the template <script> tag out from within the <select>, just for clarity. This will make the HTML easier to read and clearly separate the <select> menu from the template.
<select class="custom-select" id="inputGroupSelect01" onChange="takeSelectedSourceValue(this);">
<option id="source-language" value="" selected disabled>Auto</option>
</select>
<script type="text/handlebar-template" id="selectPersonTemplate">
{{#each people}}
<option value="{{valueLang}}">{{htmlLang}}</option>
{{/each}}
</script>
Next, we want to be sure to append html to our #inputGroupSelect01 element.
// append the HTML to the #inputGroupSelect01 select element.
$("#inputGroupSelect01").append(html);
I have created a fiddle for your reference.
The answer form Steve is perfectly fine and his fiddle also works fine. I would like to add some comments though and simplify the result:
About the closing tag </select>: Whenever you want to extend your existing HTML with Handlebars rendered HTML, you need to start with a valid HTML. In your case the browser already rendered the "invalid" <select> (invalid because the closing tag was missing). Most browsers then try to fix this by adding the closing tag,... but with your template you tried to add another one, and this doesn't work. I can see why you did this as you wanted to "complete" the <select> tag within your template, but this was too late already as the tag was rendered before your template got a chance to do so.
Conclusion: before your javaScript kicks in, the HTML is already rendered, even though it might be invalid HTML, so you need to make sure that it is valid before you manipulate the DOM.
The rest of what was going on (or wrong) was described by Steve...
To keep things simple I would probably even add the whole <select> inside the template so you need less references to HTMLElements and avoid complexity:
<script type="text/handlebar-template" id="selectPersonTemplate">
<select class="custom-select" onChange="takeSelectedSourceValue(this);">
<option id="source-language" value="" selected disabled>Auto</option>
{{#each people}}
<option value="{{valueLang}}">{{htmlLang}}</option>
{{/each}}
</select>
</script>
and then the JS (only parts of the JS from the fiddle):
// Get the template for Handlebars.
// Put whole <select> inside template to keep things simple
var template = $("#selectPersonTemplate");
// Compile the Handlebars template.
var selectPersonTemplate = Handlebars.compile(template.html());
// Evaluate the template with an array of people.
var html = selectPersonTemplate({ people: people });
// Two ways of attaching the HTML to the DOM
// $(html).insertAfter(template);
template.replaceWith(html); // removes script at the same time
By just looking at the template and the code you might realise that everything seems to be clear and simple and not spread around any more.
Here the slightly changed fiddle from Steve.

how to choose selected option in select/option in HTML?

I need to display two select lists with the same options (there are many).
I have the index.html:
<body>
<select class="c_select1"></select>
<select class="c_select2"></select>
</body>
and in another html file (options.html) all the options (only the options):
<option value='AED' title='United Arab Emirates Dirham'>AED</option>
<option value='AFN' title='Afghan Afghani'>AFN</option>
<option value='ALL' title='Albanian Lek'>ALL</option>
<option value='AMD' title='Armenian Dram'>AMD</option>
<option value='ANG' title='Netherlands Antillean Guilder'>ANG</option>
...
<option value='AOA' title='Angolan Kwanza'>AOA</option>
<option value='ARS' title='Argentine Peso'>ARS</option>
<option value='AUD' title='Australian Dollar'>AUD</option>
<option value='AWG' title='Aruban Florin'>AWG</option>
<option value='AZN' title='Azerbaijani Manat'>AZN</option>
Then, using jQuery, I load options inside the two select tags with the same instruction with different class selector:
$(".c_select1").load("options.html");
I'd like to display as default selected option two different values (since I need to show a currency converter).
I've tried in 2 different ways, but any of these works fine (I show the code for just one).
<script type="text/javascript">
$(".c_select1").load("options.html");
$(".c_select1 option[value=ARS]").prop("selected", true);
</script>
or
$(".c_select1").val("ARS");
I don't know why, but I think there is a problem with the .load() of jQuery.
The only solutions that work are 2:
set a timer and execute the second jQuery statement after this timer
use 2 different options.html files one for each select tag, but I think it is not so clever.
Is there a better way to do this dynamically?
Try this:
$(".c_select1").load("options.html", function(){
$(".c_select1").val("ARS");
});
Explained:
The .load() jQuery method requires some time to get the contents of options.html (even if its just a few milliseconds). The browser doesn't wait for it before continuing to run the rest of the javascript logic. The function(){ I added to your .load( method call is some javascript logic that runs AFTER the results have returned (aka a "callback").
Use a callback :
$(".c_select1").load("options.html", function() {
$(".c_select1").val("ARS");
});
$(".c_select2").load("options.html", function() {
$(".c_select2").val("ARS");
});
Actually there is a delay of load method that is why selected item is not working. Like #Joulss said use callback method that should work. You can see the here.
$(function(){
$(".c_select1").load("option.html", function() {
$(".c_select1").val("AFN");
});
$(".c_select2").load("option.html", function() {
$(".c_select2").val("ANG");
});
});
Demo

Select2 and Meteor.js how to?

I've only been using javascript / jquery and meteor for a couple of weeks now, so forgive me for asking what will be a simple question.
I'm trying to use Select2 in my Meteor.js app, and can't figure out how to get it working. I have installed natestrauser:select2 in my project and my jsfiddle shown just won't work. https://jsfiddle.net/jt0jr9uk
Template.createjob.onCreated( function() {
$("clientlist").select2({
placeholder: "Select a client",
allowClear: false,
});
});
And html:
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<select id="clientList" class="form-control">
<option value=""></option>
<option value="aberfitch">Abercrombie & Fitch</option>
<option value="bent">Bentley</option>
<option value="barb">Barbour</option>
<option value="dcsh">DC Shoes</option>
<option value="echo">ECHO United</option>
</select>
I'm using bootstrap also. Which I've added to my project. And basically I just want the single select box as shown here https://select2.github.io/examples.html#single
Should I be using any imports, or anything?
So first of all, on js level you tried to select an id, named clientlist
Template.createjob.onCreated( function() {
$("clientlist").select2({....
However, on html level, your id is defined in camelCase
<select id="clientList" class="form-control">
Second of all, when you select an id, you should use # sign before the id, what I mean is your jquery should look like this to achive the desired result:
Template.createjob.onCreated( function() {
$("#clientList").select2({
placeholder: "Select a client",
allowClear: false,
});
});
You need to import jquery on top of the document if you use meteor >1.3 as
import { $ } from 'meteor/jquery';
As a final suggestion, I would use Template.createjob.onRendered() instead for Template.createjob.onCreated()
The template rendered callback is fired after the DOM is rendered on
screen. The created callback is fired when the Template is
instantiated but not yet rendered
Check the following link for the full explanation https://stackoverflow.com/a/28783762/7235661

Odoo PoS dropdown from Many2one (widget.pos?)

I want to add a dropdown from a Many2one I've created to the pos.xml file (I know how to inherit from this), can someone help me with this?
I saw in the code that for every dropdown they used widget.pos.name, but this I can't seem to find it anywhere. Here is an example for countries (here I want to replace it by my variable).
<select class='detail client-address-country' name='country_id'>
<option value=''>None</option>
<t t-foreach='widget.pos.countries' t-as='country'>
<option t-att-value='country.id' t-att-selected="partner_country_id ? ((country.id === partner.country_id[0]) ? true : undefined) : undefined">
<t t-esc='country.name'/>
</option>
</t>
</select>
I don't know where the t-foreach='widget.pos.countries' comes from and how I can manage this for my own variable called "domain" which is part of a class "domainnames". And called from a Many2one from res.partner
Your Que: I saw in the code that for every dropdown they used widget.pos.name, but this I can't seem to find it anywhere.
Answer: widget.pos.name come from the In POS, models.js line No: 130., Here Server side model are loaded. This is the list of the models that need to be loaded from the server. in your custom module you can also load other models according to your requirement.
Que: I don't know where the t-foreach='widget.pos.countries' comes from and how I can manage this for my own variable?
Answer: For Country widget, it comes from models.js line No: 178, model:'res.country' loaded from the server.
In line 180: You can see that in loaded function they define countries(loaded: function(self,countries)) // You can give any naming conventions here.
So you can directly pass that function parameters in your (Many2One Field) xml file.
Example:
Write in your JS File of custom module:
module.PosModel.prototype.models.push({ //loaded model
model: 'res.partner',
fields: ['partner_id','name'],
loaded: function(self,partners){ //pass parameters
self.partners = partners;
},
});
In XML File:
<div class='client-detail'>
<span class='label'>Partner</span>
<select class='detail client-partner' name='partner_id'>
<option value=''>None</option>
<t t-foreach='widget.pos.partners' t-as='partner'>
<option t-att-value='partner.id' t-att-selected="partner_partner_id ? ((partner.id === partner.partner_id) ? true : undefined) : undefined">
<t t-esc='partner.name'/>
</option>
</t>
</select>
</div>
So, Just like that: In your js, you can load any of the model here and fetch data in your XML file.
Hope this will help you..!!!
Thanks...!!!

AngularJS ng-repeat filter function not filtering properly

I have ui-select2 dropdown that depends on the selection of a parent. I have a array of options for the first ui-select2, then when something is selected from that dropdown, the next dropdown will appear. The available options for the 2nd dropdown will depend on what is selected in the first dropdown. The ng-repeat directive is iterating over an array of choices. Here is the html and the js code.
HTML:
<select name="application" placeholder="Select a Tenant"
ng-disabled="!sharedObj.tenantApplications ||
sharedObj.tenantApplications.length == null"
class="form-control" id="application"
ng-change="vmOrderItem.vmNameUSI=null" ui-select2
ng-model="vmOrderItem.tenantApplication" title="Select tenant application"
data-style="btn-default" required><option></option>
<option ng-repeat="tenantApplication in sharedObj.tenantApplications |
filter:tenantFilter()" value="{{tenantApplication.id}}">{{tenantApplication.name}}
</option>
</select>
JS:
/** Filters the tenant depending on what domain is selected */
$scope.tenantFilter = function(tenantApplication) {
$scope.sharedObj.tenantApplications;
tenantApplication.name;
tenantApplication.id;
return true;
/* return $scope.vmOrderItem.domain.id == tenantApplication.domainId;*/
}
The issue I get is that even if I return true, nothing ever shows up on the dropdown. I did this to test the logic. I don't know why the tenantApplication parameter is always undefined in the function. I used google chrome inspect element to insert a breakpoint and it complains that the argument is undefined. But I don't see why it wouldn't work properly when I return true. I'm a newbie to JavaScript and AngularJS so any help is greatly appreciated. I've worked through all the AngularJS examples and read their docs but I'm still just a beginner.
Think this should be:
<option ng-repeat="tenantApplication in sharedObj.tenantApplications |
filter:tenantFilter" value="{{tenantApplication.id}}">

Categories

Resources