Reputation: 110960
Given the select box below. I want to be able to dynamically add a new option.
<select id="user_department_id" name="user[department_id]">
<option value=""> </option>
<option value="9">AAAAA</option>
<option value="11">BBBBB</option>
<option value="10">G</option>
<option value="12">Z</option>
<option value="">--</option>
<option value="add">Add a New</option>
</select>
I have been using the following to add a new option:
$('#user_department_id')
.prepend($("<option></option>")
.attr("value",data.id)
.text(data.title)
);
The problem here is that it is position unnaturally, it's above the empty placeholder option and not sorted alphabetically. Is there a magic way to append a new select option in the correct place?
Thanks
Upvotes: 5
Views: 6317
Reputation: 95
This inserts a new option value into (assuming it is already sorted)
$('#yourselectID option').each(function()
{
var option = $(this).text();
option = option.toLowerCase();
var test = option.toLowerCase();
if ( option > test)
{
$(this).before('<option value="'+test+'">' + test+ '</option>');
return false;
}
});
Upvotes: 3
Reputation: 5353
You can use underscore's sortedIndex
to figure out where to insert the item and then jquery's after
function to insert it at that position. This is assuming you want to sort by option text alphabetically:
var option = '<option value="' + data.id + '">' + data.title + '</option>';
var index = _.sortedIndex($('#user_department_id option'), option, function(item) {
return $(item).text();
});
if(index === 0) {
$('#user_department_id').prepend(option);
} else {
$('#user_department_id option').eq(index - 1).after(option);
}
Upvotes: 0
Reputation: 30252
Not very elegant, but this should do:
$('#user_department_id option').each(function() {
if(this.text > data.title) {
$(this).before('<option value="' + data.id + '">' + data.title + '</option>');
return false;
}
});
Upvotes: 0
Reputation: 30099
Keep your options in an array of objects and generate your select from that object. Then add your new items to that array and regenerate your select.
$(function() {
// Any options always on the top
var topOptions = '<option value=""> </option>';
// Your middle, sorted options
var options = [{val: 9, text: "AAAAA"}, {val: 11, text: "BBBBB"},{val: 10, text: "G"},{val: 12, text: "Z"}];
// Any options always on the bottom
var bottomOptions = '<option value="">--</option><option value="add">Add a New</option>';
// Function to populate the select options from above data
function populateOptions(element, options) {
// Sort options
options = options.sort(function(a, b) {
return a.text.toLowerCase() > b.text.toLowerCase();
});
$(element).html('').append(topOptions);
for (var i = 0; i < options.length; i++) {
$('<option>').attr("value", options[i].val).text(options[i].text).appendTo($(element));
}
$(element).append(bottomOptions);
}
// Start by populating the select
populateOptions('#user_department_id', options);
// Add and repopulate when add requested
$('#user_department_id').on('change', function() {
if ($(this).val() == "add") {
// Add option to list
options.push({val: data.id, text: data.text});
// Repopulate select
populateOptions(this, options);
// Select the new item
$(this).val(data.id);
}
});
});
Demo: http://jsfiddle.net/kfC3S/
Upvotes: 0
Reputation: 79830
As mentioned in my comment, you can remove the option that you don't want to sort and then add them back.
Note: The below will work in your case because you want the --
and Add New
at the end.
var selElem = document.getElementById('user_department_id')
var tmpAry = [];
var igOpt = [];
for (var i = 0; i < selElem.options.length; i++) {
if ($(selElem.options[i]).hasClass('ig')) {
igOpt.push([selElem.options[i].text,
selElem.options[i].value]);
continue;
}
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
tmpAry.sort();
//merge with ignored options
tmpAry = tmpAry.concat(igOpt);
//remove options
$(selElem).empty();
for (var i = 0; i < tmpAry.length; i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
Upvotes: 1
Reputation: 390
I think you can use .after('blah') with the selector you described.
for example:
$('#user_department_id option[value="12"]').after('<option value="13">Q</option>')
is that of any use?
Upvotes: 1