Jquery append html element to div after for loop, strange behaviour - javascript

Here is the code:
$('#date').append(
'<select id="date">'+
'<option value="0">- - SELECT - -</option>');
for(var i in data){
$('#date').append(
'<option value="">'+data[i]['date_time']+'</option>');
});
$('#date').append('</select>');
</select> is always added above for loop. If i replace it with just work select for example, it is appended at the end, where it should be. Why is this happening and how can i fix it?

I believe that jQuery will generate the DOM like this:
<div id="date">
<select id="date">
<option value="0">- - SELECT - -</option>
</select>
<option value="">foo</option>
<option value="">bar</option>
etc...
</div>
Since it is automatically closing the <select> after the first .append(). What you are doing afterwards is appending the options to the <div id="#date"/> rather than the <select> that was appended. I don't think the final closing </select> will actually do anything either.
If you really want to use append the following JavaScript will add the options to the correct node:
// dummy data object for example
var data = new Array(new Array(), new Array());
data[0].date_time = 2011;
data[1].date_time = 2012;
var options = new Array();
$.each(data, function(index, option) {
options.push('<option value="' + index + '">'+ option.date_time +'</option>');
});
$('<select id="date"/>').append(options.join('')).appendTo('#date');
Assuming the existing HTML:
<div id="date"></div>
However this does incur an overhead since appending is occurring twice. The faster approach is to build up the options markup as already answered by ShankarSangoli

It is not the right way to create html dynamically. You should create the complete markup all at once by putting it into an array and then provide it to jQuery. Try this
var html = [];
html.push('<select id="date">');
html.push('<option value="0">- - SELECT - -</option>');
for(var i in data){
html.push('<option value="">'+data[i]['date_time']+'</option>');
}
html.push('</select>');
//This selector should be some container like dateContainer
//because you have already give date as id to the above select element
$('#dateContainer').html(html.join(''));

$('#date').append($("<select/>", { name: "name"+i})
.find('select')
.append($("<option/>", { value: "abc"+i}).text('cell'))
.append($("<option/>", { value: "abc"+i}).text('home'))
.append($("<option/>", { value: "abc"+i}).text('work'));
all options should wrap inside select

I imagine the base HTML you have looks something like this:
<div id="date"></div>
then after the first $('#date').append('<select id="date">... in your code, you will have this:
<div id="date"><select id="date">...</div>
which is 2 elements with the same ID attribute.
The ID attribute is like the highlanders, there must only be one of them (in each page).
The seccond $('#date').append... works unexpectedly, and the 3rd one, also unexpectedly, doesn't work. Because you can't predict to which #date they are referring.
Also, as the other answers say, it will be better if you build it to do only 1 append, because calling the selectors so many times (especially inside the loop) it's a performance hit.

If you want to do it in your way - create, for example, string variable with html code in it and than append it.
data = [1, 2, 3];
var html = '<select id="date">'+
'<option value="0">- - SELECT - -</option>';
for(var i in data){
html += '<option value="">'+data[i]+'</option>';
}
$('#date').append(html)
or look here
What is the best way to add options to a select from an array with jQuery?
ps: the first append tries to create a valid DOM structure inside of document, closing select tag automatically. that is why the second one will not insert options into the created select.
another possible way, based on the link above, is
var sel = $('<select id="date">');
$.each(data, function(key, value) {
sel.append($('<option>').text(key['date_time']));
});
$('#date').append(sel);

Related

Create a string containg optgroup and option in jquery

I'm trying to create a string variable to append on a multiselect with jquery.
This is the fiddle example: https://jsfiddle.net/o2gxgz9r/47084/
$(document).ready(function() {
var group = "<optgroup></optgroup>";
$(group).attr("value", 1);
$(group).attr("label", "test group");
var t = "<option></option>";
$(t).attr("value", 4);
$(t).text("Test option");
$(t).attr("selected", true);
$(group).append(t);
$("#a").html(group);
});
body {
padding: 5px;
}
label {
font-weight: bold;
}
input[type=text] {
width: 20em
}
p {
margin: 1em 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
RESULT TEST PURPOSE:
<br><br>
EXPECTED:
<br>
<textarea rows="5" cols="72">
<optgroup value="1" label="test group">
<option value="4" selected>Test option</option>
</optgroup>"
</textarea>
<br><br>
GET:
<br>
<label id="a"></label>
Next step is to append the string created dinamically in a select with
$("#select").append(group);
But the string is not created...it result empty
There's a few issues here. Firstly you're attempting to append an optgroup element to a label. This is impossible as optgroup can only be children of select elements.
Secondly, optgroup elements do not have a value attribute.
Finally, you're repeatedly creating new jQuery objects for group and t, which means that all previous amendments are lost. To fix this create the jQuery objects once and store them in variables which you can then reference whenever you want to make a change. Try this:
$(document).ready(function() {
var $group = $('<optgroup></optgroup>');
$group.prop("label", "test group");
var $t = $('<option></option>');
$t.val(4);
$t.prop("selected", true);
$t.text("Test option");
$group.append($t);
$("#a").html($group);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<select id="a"></select>
Note the use of val() to set the value attribute, and the use of prop() over attr() where possible.
There are several issues:
var group = "<optgroup></optgroup>";
$(group).attr("value", 1);
You are referring to the JQuery element incorrectly. What goes inside $() needs to be a string representing an element, a class, or an id. So if you want to change all existing optgroups, it should look like this:
var group = "optgroup";
$(group).attr("value", 1);
However, based on the rest of your code that doesn't seem to be your intention. If you are wanting to create a new optgroup, then you'll need to reference an element already in the DOM to add it to (i.e. your #select).
Second, your optgroup element cannot have a value, that is invalid HTML. An optgroup is a non-selectable "label" that helps break up options in a dropdown.
Third, you are creating your <option> element incorrectly. As mentioned before, you can't create a JQuery element with a string of an open/close for an element. You'd be better off doing something like this:
var t = "<option value='4' selected='selected'>Test option</option>";
$(group).append(t);
So your code should actually look something like this:
var group = "<optgroup label='test group'>";
group += "<option value='4' selected='selected'>Test option</option>";
group += "</optgroup>";
$("#select").append(group);
If you have at least JQuery 1.8, you can change it to this:
var group = $( "<optgroup/>", { "label" : "test group"});
var option = $( "<option/>", { text : "Test option", "value" : 4, "selected" : "selected" });
group.appendTo( "#select" );
option.appendTo(group);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<select id="select"></select>

Accessing child element property through parent element property with DOM

I'm trying to show a child element property from 'select' tag and I using document.getElementsByTagName command to do that, the display that I expect is 'john dalton' look source bellow!, but browser not display as I expect just undefined message in alert. my source like this:
<select style="" name="provinsi_id" class="form-control crud-edit
lookup-refresh" onchange="showoption();">
<option>john dalton</option>
<option>john rambo</option>
<script>
alert(document.getElementsByTagName('select')[0].childNodes[0].value);
<script>
try this,
alert(document.getElementsByTagName('select')[0].childNodes[1].value);
0th element is a text element.
Note: Whitespace inside elements is considered as text, and text is considered as nodes. Comments are also considered as nodes.
When you have a <select> you can access to the options easily.
document.getElementsByTagName('select')[0].options
The "options" is an array of all the options in your select, so you can acces to your value this way:
document.getElementsByTagName('select')[0].options[0].value
You also have a shortcut by doing this:
document.getElementsByTagName('select')[0][0].value
every answer runing well, if I write static code as Nannakuhtum's sample, unfortunately in my case I use javascript to fill option value dynamicly like this,
<html>
--------
<select style="" name="provinsi_id"
class="form-control crud-edit
lookup-refresh" onchange="tampilkota();">
</select>
------------
</html>
<script>
var dataprovinsi = <?php echo json_encode($dataprovinsi); ?>;
for (i=0; i< dataprovinsi.length; i++){
var option = document.createElement("option");
option.text = dataprovinsi[i]['nama'];
option.value = dataprovinsi[i]['nama'];
var select = document.getElementById("psg_provinsi_id");
select.appendChild(option);
}
function tampilkota(){
alert(document.getElementsByTagName('select')[0].childNodes[1].value);
}

Populate Select With OptGroup From Two Seperate JSon Objects JQuery

I have two json objects
var type = [{"Id":1,"Name":"This is a name"}];
var subType = [{"Id":2,"ParentId":1,"Name":"This is a name"},];
subType.ParentId references the type.Id
I want to be able to populate a select in jQuery having
<SELECT>
<OPTGROUP LABEL="type.Name" id="type.Id">
<OPTION LABEL="subType.Name" value="subType.Id">subType.Name</OPTION>
</OPTGROUP>
</SELECT>
The code below uses just "select" as a jquery selector, so it will affect all selectboxes on the page.
You probably want to change this.
The code below also does not handle having one of the options selected which is probably something you should watch out for.
var type = [{"Id":1,"Name":"This is a name"}];
var subType = [{"Id":2,"ParentId":1,"Name":"This is a name"}];
var output = [];
$.each(type, function(){
//for each type add an optgroup
output.push('<optgroup label="'+this.Name+'">');
var curId = this.Id;
//linear search subTypes array for matching ParentId
$.each(subType, function(k,v){
if( this.ParentId = curId ){
output.push('<option label="'+this.Name +'" value="'+ this.Id +'">'+ this.Name +'</option>');
//DELETE the element from subType array so the next search takes less time
subType.splice(k,1);
}
});
output.push('</optgroup>');
});
//change the 'select' here to the id of your selectbox
$('select').html(output.join(''));
Adding optgroups to select using javascript dynamically
You able criate dinamamicaly the combo. Access The values of json is In this question.
How to access Json Object which has space in its name?
Have some situations in posts to resolve your question.

jquery empty() preventing select

A while ago I posted this question asking how to get JSON data into jQuery dropdowns
jquery dropdown from mysql based on previous selection
Well the people here were awesome and I got a solution. The problem I'm having now is that the suggest solution dosen't work in my production enviorment but it does in my test.
In order to prevent duplicate entrees I am using jQuery empty() the problem is that using empty() seems to also be preventing me from selecting the first option.
this is the function that is generating the optiosn from JSON
function(data){
var select = $('[name="employee_manager"]');
select.empty();
select.append(new Option(ucfirst('No Manager'),'100'));
$.each(data, function(index, array) {
select.append(new Option(ucfirst(array['first_name'])+ " "+ucfirst(array['last_name']),array['id']));
});
Is that an alternative to empty() that won't prevent selection?
EDIT This seems to only be a problem if there are fewer than two items being dynamically input
EDIT 2 Here is the HTML. It seems that I can't select the first option if empty() is present
<label for="manager">Reports To</label>
<select name="employee_manager">
<option value="1">Please Select Employee Role</option>
<option value="2">John Doe</option>
<option value="3">James Smith</option>
</select>
EDIT 3
Looks like the empty class is adding a span to my select
<div class="selector">
<span style="-moz-user-select: none;">Jane Smith</span>
<select name="employee_manager" style="opacity: 0;">
<option value="100">No Manager</option>
</select>
</div>
EDIT 4
Okay so here is a jsfiddle that shows the problem. I couldn't get the JSON data to load correctly but you can still see the problem if you attempt to click on the first item in the list. It seems that it's a problem with uniformjs as if uniform is removed it's not a problem
http://jsfiddle.net/BandonRandon/xXUfp/1/
Don't use empty() to clear the options of drop down list. It's wrong, because it should be used to remove DOM children.
Instead use such code:
$("select[name='employee_manager'] > option").remove();
Edit: when using the jQuery uniform plugin, dynamically adding options is messing things up... one way around that does not require to go and try fix the plugin is to always have enough "dummy" options in place (e.g. 20 if that's the max amount of options) then change the text/value of those options and hide all others according to your data.
The proper JS code will now look like this:
var myData = [];
myData.push( { text: "Please Select A Manager (JS)", value: "null" } );
myData.push( { text: "No Manager", value: "100" } );
myData.push( { text: ucfirst("a third choice"), value: "42" } );
$.each(data, function(index, array) {
myData.push( { text: ucfirst(array['first_name'])+ " " + ucfirst(array['last_name']), value: array['id'] } );
});
$("select[name='employee_manager'] > option").each(function(index) {
if (index < myData.length) {
$(this).text(myData[index]["text"]);
$(this).val(myData[index]["value"]);
$(this).show();
}
else {
$(this).hide();
}
});
Updated jsFiddle.
Crude, but working.... :)
Well try something like this, but no guaranteed
$('<option></option>').val(100).html('No Manager').appendTo($(select));
$.each(data, function(index, array) {
$('<option></option>').val(array['id']).html(ucfirst(array['first_name'])+ " "+ucfirst(array['last_name']).appendTo($(select));
});

How do you remove all the options of a select box and then add one option and select it with jQuery?

Using core jQuery, how do you remove all the options of a select box, then add one option and select it?
My select box is the following.
<Select id="mySelect" size="9"> </Select>
EDIT: The following code was helpful with chaining. However, (in Internet Explorer) .val('whatever') did not select the option that was added. (I did use the same 'value' in both .append and .val.)
$('#mySelect').find('option').remove().end()
.append('<option value="whatever">text</option>').val('whatever');
EDIT: Trying to get it to mimic this code, I use the following code whenever the page/form is reset. This select box is populated by a set of radio buttons. .focus() was closer, but the option did not appear selected like it does with .selected= "true". Nothing is wrong with my existing code - I am just trying to learn jQuery.
var mySelect = document.getElementById('mySelect');
mySelect.options.length = 0;
mySelect.options[0] = new Option ("Foo (only choice)", "Foo");
mySelect.options[0].selected="true";
EDIT: selected answer was close to what I needed. This worked for me:
$('#mySelect').children().remove().end()
.append('<option selected value="whatever">text</option>') ;
But both answers led me to my final solution..
$('#mySelect')
.find('option')
.remove()
.end()
.append('<option value="whatever">text</option>')
.val('whatever')
;
$('#mySelect')
.empty()
.append('<option selected="selected" value="whatever">text</option>')
;
why not just use plain javascript?
document.getElementById("selectID").options.length = 0;
If your goal is to remove all the options from the select except the first one (typically the 'Please pick an item' option) you could use:
$('#mySelect').find('option:not(:first)').remove();
I had a bug in IE7 (works fine in IE6) where using the above jQuery methods would clear the select in the DOM but not on screen. Using the IE Developer Toolbar I could confirm that the select had been cleared and had the new items, but visually the select still showed the old items - even though you could not select them.
The fix was to use standard DOM methods/properites (as the poster original had) to clear rather than jQuery - still using jQuery to add options.
$('#mySelect')[0].options.length = 0;
Not sure exactly what you mean by "add one and select it", since it will be selected by default anyway. But, if you were to add more than one, it would make more sense. How about something like:
$('select').children().remove();
$('select').append('<option id="foo">foo</option>');
$('#foo').focus();
Response to "EDIT": Can you clarify what you mean by "This select box is populated by a set of radio buttons"? A <select> element cannot (legally) contain <input type="radio"> elements.
$('#mySelect')
.empty()
.append('<option value="whatever">text</option>')
.find('option:first')
.attr("selected","selected")
;
$("#control").html("<option selected=\"selected\">The Option...</option>");
Just one line to remove all options from the select tag and after you can add any options then make second line to add options.
$('.ddlsl').empty();
$('.ddlsl').append(new Option('Select all', 'all'));
One more short way but didn't tried
$('.ddlsl').empty().append(new Option('Select all', 'all'));
Thanks to the answers I received, I was able to create something like the following, which suits my needs. My question was somewhat ambiguous. Thanks for following up. My final problem was solved by including "selected" in the option that I wanted selected.
$(function() {
$('#mySelect').children().remove().end().append('<option selected value="One">One option</option>') ; // clear the select box, then add one option which is selected
$("input[name='myRadio']").filter( "[value='1']" ).attr( "checked", "checked" ); // select radio button with value 1
// Bind click event to each radio button.
$("input[name='myRadio']").bind("click",
function() {
switch(this.value) {
case "1":
$('#mySelect').find('option').remove().end().append('<option selected value="One">One option</option>') ;
break ;
case "2":
$('#mySelect').find('option').remove() ;
var items = ["Item1", "Item2", "Item3"] ; // Set locally for demo
var options = '' ;
for (var i = 0; i < items.length; i++) {
if (i==0) {
options += '<option selected value="' + items[i] + '">' + items[i] + '</option>';
}
else {
options += '<option value="' + items[i] + '">' + items[i] + '</option>';
}
}
$('#mySelect').html(options); // Populate select box with array
break ;
} // Switch end
} // Bind function end
); // bind end
}); // Event listener end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>One<input name="myRadio" type="radio" value="1" /></label>
<label>Two<input name="myRadio" type="radio" value="2" /></label>
<select id="mySelect" size="9"></select>
I've found on the net something like below. With a thousands of options like in my situation this is a lot faster than .empty() or .find().remove() from jQuery.
var ClearOptionsFast = function(id) {
var selectObj = document.getElementById(id);
var selectParentNode = selectObj.parentNode;
var newSelectObj = selectObj.cloneNode(false); // Make a shallow copy
selectParentNode.replaceChild(newSelectObj, selectObj);
return newSelectObj;
}
More info here.
$("#id option").remove();
$("#id").append('<option value="testValue" >TestText</option>');
The first line of code will remove all the options of a select box as no option find criteria has been mentioned.
The second line of code will add the Option with the specified value("testValue") and Text("TestText").
Building on mauretto's answer, this is a little easier to read and understand:
$('#mySelect').find('option').not(':first').remove();
To remove all the options except one with a specific value, you can use this:
$('#mySelect').find('option').not('[value=123]').remove();
This would be better if the option to be added was already there.
How about just changing the html to new data.
$('#mySelect').html('<option value="whatever">text</option>');
Another example:
$('#mySelect').html('
<option value="1" selected>text1</option>
<option value="2">text2</option>
<option value="3" disabled>text3</option>
');
Another way:
$('#select').empty().append($('<option>').text('---------').attr('value',''));
Under this link, there are good practices https://api.jquery.com/select/
First clear all exisiting option execpt the first one(--Select--)
Append new option values using loop one by one
$('#ddlCustomer').find('option:not(:first)').remove();
for (var i = 0; i < oResult.length; i++) {
$("#ddlCustomer").append(new Option(oResult[i].CustomerName, oResult[i].CustomerID + '/' + oResult[i].ID));
}
Uses the jquery prop() to clear the selected option
$('#mySelect option:selected').prop('selected', false);
This will replace your existing mySelect with a new mySelect.
$('#mySelect').replaceWith('<Select id="mySelect" size="9">
<option value="whatever" selected="selected" >text</option>
</Select>');
You can do simply by replacing html
$('#mySelect')
.html('<option value="whatever" selected>text</option>')
.trigger('change');
I saw this code in Select2 -
Clearing Selections
$('#mySelect').val(null).trigger('change');
This code works well with jQuery even without Select2
Cleaner give me Like it
let data= []
let inp = $('#mySelect')
inp.empty()
data.forEach(el=> inp.append( new Option(el.Nombre, el.Id) ))
save the option values to be appended in an object
clear existing options in the select tag
iterate the list object and append the contents to the intended select tag
var listToAppend = {'':'Select Vehicle','mc': 'Motor Cyle', 'tr': 'Tricycle'};
$('#selectID').empty();
$.each(listToAppend, function(val, text) {
$('#selectID').append( new Option(text,val) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I used vanilla javascript
let select = document.getElementById("mySelect");
select.innerHTML = "";
Hope it will work
$('#myselect').find('option').remove()
.append($('<option></option>').val('value1').html('option1'));
var select = $('#mySelect');
select.find('option').remove().end()
.append($('<option/>').val('').text('Select'));
var data = [{"id":1,"title":"Option one"}, {"id":2,"title":"Option two"}];
for(var i in data) {
var d = data[i];
var option = $('<option/>').val(d.id).text(d.title);
select.append(option);
}
select.val('');
Try
mySelect.innerHTML = `<option selected value="whatever">text</option>`
function setOne() {
console.log({mySelect});
mySelect.innerHTML = `<option selected value="whatever">text</option>`;
}
<button onclick="setOne()" >set one</button>
<Select id="mySelect" size="9">
<option value="1">old1</option>
<option value="2">old2</option>
<option value="3">old3</option>
</Select>
The shortest answer:
$('#mySelect option').remove().append('<option selected value="whatever">text</option>');
Try
$('#mySelect')
.html('<option value="whatever">text</option>')
.find('option:first')
.attr("selected","selected");
OR
$('#mySelect').html('<option value="4">Value 4</option>
<option value="5">Value 5</option>
<option value="6">Value 6</option>
<option value="7">Value 7</option>
<option value="8">Value 8</option>')
.find('option:first')
.prop("selected",true);

Categories