Here is my code:
$(function () {
var region = $('#region');
var city = $('#city');
var pickedRegionId = region.find(':selected').val();
var options;
if (pickedRegionId === '') {
console.log('region is empty, html() and disable');
city.html('');
city.attr('disabled', true);
}
region.change(function(){
console.log('region is changed');
pickedRegionId = $(this).val();
if (pickedRegionId !== '') {
city.html('');
console.log('loading cities');
getCities(pickedRegionId);
}
});
function getCities (regionId) {
city.attr('disabled', true);
city.html('<option>Loading...</option>');
$.get(
'/ajax/get_cities',
'region_id='+regionId,
function (responce) {
if (responce.result === 'success') {
$(responce.cities).each(function(){
options += '<option value="'+$(this).attr('id')+'">'+$(this).attr('city')+'</option>';
});
city.html(options);
city.attr('disabled', false);
}
}, 'json'
);
}
});
When page loads all is ok, I pick some region and select with cities fills with ajax data.
But when I pick another region, data in cities select just extends with newer data.
So the problem that I have cities from both regions(new and old one). And not matter how many times I pick another region it's just adding new data to city select. In the code all looks fine and on region change I've put .html('') so it should be empty before inserting received values. But I can't figure out what the bug is.
$(responce.cities).each(function(){
options += '<option value="'+$(this).attr('id')+'">'+$(this).attr('city')+'</option>';
});
You are just appending to options and not clearing it at all. I would empty your options just below where you set cities to loading.
try reseting your "options" var before the loop:
...
options = '';
$(responce.cities).each(function(){
...
You have to empty the variable options first. You're just adding new cities to the options variable.
The simplest solution would be to move the options variable into the getCities function like this:
function getCities (regionId) {
var options = "";
city.attr('disabled', true);
city.html('<option>Loading...</option>');
$.get(
'/ajax/get_cities',
'region_id='+regionId,
function (responce) {
if (responce.result === 'success') {
$(responce.cities).each(function(){
options += '<option value="'+$(this).attr('id')+'">'+$(this).attr('city')+'</option>';
});
city.html(options);
city.attr('disabled', false);
}
}, 'json'
);
}
The problem is that, when you receive the data, you add it to the options variable that is global. So, just add this before $(responce.cities).each(function(){:
options = '';
And everything should be fine.
BTW, it's response, not responce. :)
In function getCities, add var options=''; as the first line. You're constantly adding to it but never clearing it out, hence the problem.
Two things:
1) city.attr('disabled', true); should be city.prop('disabled', 'disabled');
2) Try resetting options back to an empty string before repopulating it like so:
if (responce.result === 'success') {
options = '';
$(responce.cities).each(function(){
options += '<option value="'+$(this).attr('id')+'">'+$(this).attr('city')+'</option>';
});
city.html(options);
city.attr('disabled', false);
}
Related
The title is a bit much so let me break this down. What I am trying to accomplish here is selecting an option from select 1 (onChange) retrieves the prebuilt select for select 2 from an external php script. Same for 2 -> 3 and 3 -> 4. I know how to do this, perhaps not efficiently, but, I can get it done.
The problem I crashed into was, the 3rd select is not always an option. This is a problem because the 4th select is the end result I need. The second select in this case will give me the ID's to create select 4 instead. Make sense?
HTML:
<td>
<select name="collectionID" id="bpCollection" class="form-control">
<option value="">Select Collection</option>
<?PHP echo optionsFromDatabase();?>
</select>
</td>
<td><select name="bpClass"id="bpClass" class="form-control"></select></td>
<td><select name="bpFaction"id="bpFaction" class="form-control"></select></td>
<td><select name="bpID"id="bpID" class="form-control"></select></td>
JQUERY :
<script>
$("#bpCollection").change(function() {
$("#bpClass").load("inc/api/auto.php?type=class&choice=" + $("#bpCollection").val());
});
$("#bpClass").change(function() {
$("#bpFaction").load("inc/api/auto.php?type=faction&choice=" + $("#bpClass").val());
});
$("#bpFaction").change(function() {
$("#bpID").load("inc/api/auto.php?type=blueprint&choice=" + $("#bpFaction").val());
});
</script>
As Previously stated this does work perfectly.
Auto.php
$group = $db->escape($_GET['type']);
$choice = $db->escape($_GET['choice']);
$list = '';
switch ($group) {
case 'blueprint':
$db->where('marketGroupID',$choice);
$db->orderBy('typeName','ASC');
$map = $db->get('invTypes');
foreach ( $map as $val ) {
$list .= '<option value="'.$val['typeID'].'">'.$val['typeName'].'</option>';
}
break;
default:
$db->where('parentGroupID',$choice);
$db->orderBy('marketGroupName','ASC');
$map = $db->get('invmarketgroups');
foreach ( $map as $val ) {
$list .= '<option value="'.$val['marketGroupID'].'">'.$val['marketGroupName'].'</option>';
}
}
echo $list;
This works perfectly, except. #bpFaction is not always an option where it can't populate since #bpClass holds the ID options for #bpID. I can select the #bpClass select option and will need to jump straight to #bpID. I think a good part of the problem I have is that I don't visualize the code needed on either end to make this work properly. Do I need to make the jquery do this, do I need to change auto.php, or both?
Do you have any thoughts on how best to do it?
I recommended using Ajax with JSON above. Here I will go more in-depth of how to do that. I will be writing this sample using States, Cities, and Jurisdictions as the select box types.
We will be using one controller in PHP for all select boxes (just like yours above) except we will be re-writing it to return JSON instead. I don't know what framework you are using so I just wrote a sample of what it would look like:
// if no state passed in, return list
if(!$stateId = $request->get('state')) {
$loadedStatesFromDb = ...; // states loaded from DB
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$states = [];
foreach($loadedStatesFromDb as $state) {
$states[$state->getId()] = $state->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'states' => $states
]);
}
// if no city passed in, load cities for the selected state
if(!$cityId = $request->get('city')) {
$loadedCitiesFromDb = ...; // cities loaded from DB for $stateId
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$cities = [];
foreach($loadedCitiesFromDb as $city) {
$cities[$city->getId()] = $city->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'cities' => $cities
]);
}
// if no jurisdiction selected, load list
if(!$jurisdictionId = $request->get('jurisdiction')) {
$loadedJurisdictionsFromDb = ...; // jurisdictions loaded from DB for $cityId
// if your $loadedCitiesFromDb is an array of classes we need to format it into a flat array for JSON
$jurisdictions = [];
foreach($loadedJurisdictionsFromDb as $jurisdiction) {
$jurisdictions[$jurisdiction->getId()] = $jurisdiction->getName();
}
// your framework may require a different method of passing json data
return json_encode([
'result' => 'ok', // we pass this so the Ajax jquery call can check it returned successfully
'jurisdictions' => $jurisdictions
]);
}
And this is what your view would sort of look like (untested, but generally how you would do it):
<select name="state" id="state-select"></select>
<select name="city" id="city-select"></select>
<select name="jurisdiction" id="jurisdiction-select"></select>
<script type="text/javascript">
function _load_select_boxes(e) {
if(
$("#state-select").val() && $("#city-select").val() && $("jurisdiction-select").val() && // if we have an item selected in all select boxes
typeof e !== 'undefined' && e.target.id == 'jurisdiction-select' // if the select box that triggered the event is the last one
) {
_select_box_completed('jurisdiction', $("jurisdiction-select").val());
}
$.ajax({
url: '/where/you/load/select/boxes',
type: 'POST',
data: $("#state-select, #city-select, #jurisdiction-select").serialize(),
dataType: 'json', // what server will return
success: function (data) {
if (data.result === 'ok') {
if(typeof data.states !== 'undefined') {
// no need to reset options for the first select (unless we will be re-loading it without selecting a value)
// set select box options using the array of cities
for(var stateId in data.states) {
var stateName = data.states[stateId];
$("#city-select").append('<option value="' + stateId + '">' + stateName + '</option>')
}
} else if(typeof data.cities !== 'undefined') {
// reset select box
$('#city-select').find('option').remove();
// set select box options using the array of cities
for(var cityId in data.cities) {
var cityName = data.cities[cityId];
$("#city-select").append('<option value="' + cityId + '">' + cityName + '</option>')
}
} else if(typeof data.jurisdictions !== 'undefined') {
if(!data.jurisdictions.length) {
// no jurisdictions returned so we reached end
_select_box_completed('city', $("#city-select").val());
} else {
// reset select box
$('#jurisdiction-select').find('option').remove();
// set select box options using the array of jurisdictions
for(var jurisdictionId in data.jurisdictions) {
var jurisdictionName = data.jurisdictions[jurisdictionId];
$("#jurisdiction-select").append('<option value="' + jurisdictionId + '">' + jurisdictionName + '</option>')
}
}
}
} else {
// handle error for app
}
},
error: function (jqXHR, textStatus, errorThrown) {
// handle error for app
}
});
}
function _select_box_completed(type, id) {
// fired when we have selected as far as we can go
}
$(function(){
// this runs when page finishes loading, so we can load in the defaults and set events on the select boxes
$("#state-select, #city-select, #jurisdiction-select").on('change', function(e){
_load_select_boxes(e);
});
_load_select_boxes();
});
</script>
The simplest way to do this without changing much code is make your switch a function, build in a condition and call it again with changed parameters if that condition is met.
$list= myswitch($db, $group, $choice);
function myswitch($db, $group, $choice){
$list='';
switch ($group) {
case 'blueprint':
...
break;
default:
$db->where('parentGroupID',$choice);
$db->orderBy('marketGroupName','ASC');
$map = $db->get('invmarketgroups');
//*** CONDITION HERE ***
//IF condition met: set new variables
if($choice === ... && $map === ...)){
$group="xxx";
$choice="yyy";
//call the function again with new values
$list = myswitch($db, $group, $choice);
}
//ELSE create normal list
else{
foreach ( $map as $val ) {
$list.= ....
}
}
return list;
}
i am trying to change the second dropdown list when an item is selected on 1st dropdown
$output_body = '<select>';
$accounts = $service->management_accounts->listManagementAccounts("~all");
foreach($accounts['items'] as $item) {
$output_body .= sprintf('<option value="%d">%s</option>', $item['id'], $item['name']);
}
$output_body .= '</select>';
so when i select an item from above dropdown list it should store value of selected item in variable and that variable will be used here which i believe update the dropdown list
$webproperties = $service->management_webproperties->listManagementWebproperties("var here");
foreach($webproperties['items'] as $item) {
$output_prop .= sprintf('<option value="">%s</option>', $item['name']);
}
$output_prop .= '</select>';
Here is a good example for cascading dropdowns in jQuery. (populating one based on the selection of another)
<script>
$(function () {
var productsSelect = $('#productId');
productsSelect.attr('disabled', true);
$('#categoryId').change(function () {
var categoryId = $(this).val();
$.getJSON('/GetProducts/' + categoryId, function (products) {
productsSelect.attr('disabled', false);
productsSelect.empty();
productsSelect.append(
$('<option/>')
.attr('value', '')
.text('-- Select Product --'));
$.each(products, function (index, product) {
productsSelect.append(
$('<option/>')
.attr('value', product.ProductId)
.text(product.ProductName)
);
});
});
});
});
</script>
It would be nice in my opinion to be able to use event bubbling on the parent element in conjunction with a html data element, submit the request to your php controller and assign the option data back to your view, but I'm not sure if you have the mvc framework to support this or not...
window.addEvent('domready', function() {
$('parent_option_list_container').addEvent('click:relay(a)', function(e, ele) {
if (ele.hasClass('some_option_in_the_list')) {
e.preventDefault();
var selected = ele.get('data-option-value');
var request = new Request({
method: 'POST',
url : '/form_controller/option_select_toggle_function/' + selected,
}).send();
}
}
I have this HTML list
<ul id='usernameList'>
<li class='username'>John</li>
<li class='username'>Mark</li>
</ul>
and a form to add new names via AJAX, multiple add separated by commas. The response is a list with the names
[{name:David, newUser:yes}, {name:Sara, newUser:yes}, {name:Mark, newUser:no}]
I'm trying to insert this names sorted alphabetically in the list, like this example https://jsfiddle.net/VQu3S/7/
This is my AJAX submit
var form = $('#formUsername');
form.submit(function () {
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize(),
dataType: "json",
beforeSend: function () {
//
},
success: function (data) {
var listUsernames = $('#usernameList');
var numUsernames = listUsernames.children().length;
$.each(data, function(i, user) {
if(user.newUser == "yes"){
var htmlUser = "<li class='username'>" + user.name + "</li>";
var added = false;
$(".username", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
}
});
if(!added)
$(htmlUser).appendTo($(listUsernames));
}
// HERE I DO alert('numUsernames')
// I get the same number of users before sending form
// How can I update here the value of listUsernames and numUsernames?
});
}
});
return false;
});
My question is, how I can update the value of listUsernames and numUsernames after adding an item?
You just need to update numUsernames at that point.
Add this where your comments are:
numUsernames = listUsernames.children().length;
listUsernames already has the updated children, as it's a reference to the parent element.
Edit: Re: your comment below:
This should probably work:
$(".username", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
return false; // stop `.each` loop.
}
});
First you don't need a double jQuery wrapping:
$(htmlUser).appendTo($(listUsernames));
listUsernames is already a jQuery object, so try:
$(htmlUser).appendTo(listUsernames);
And after every adding, you can update the numUsernames variable with:
numUsernames = listUsernames.children().length;
but this is not necessary because you can always access listUsernames.children().length in the success handler.
I update your JSFiddle
var listUsernames = $('#usernameList');
var numUsernames = listUsernames.children().length;
var data = [{name:'David', newUser:'yes'}, {name:'Sara', newUser:'yes'}, {name:'Mark', newUser:'no'}]
$.each(data, function(i, user) {
if(user.newUser == "yes"){
var htmlUser = "<li class='username'>" + user.name + "</li>";
var added = false;
$(".ingredient", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
}
});
if(!added)
$(htmlUser).appendTo($(listUsernames));
}
// HERE I DO alert('numUsernames')
// I get the same number of users before sending form
// How can I update here the value of listUsernames and numUsernames?
});
I have a following problem with jQuery. I use this code:
function populate_select_from_json(select, json_url) {
select.empty();
$.getJSON(json_url, function(data) {
$.each(data, function(key, value) {
$("<option></option>")
.attr("value", value.name)
.text(value.title)
.appendTo(select);
});
});
select.children(":first").attr("selected", true);
}
$(document).ready(function() {
var value_type = $("#value_type");
populate_select_from_json(value_type, SOME_URL);
var unit = $("#unit");
populate_select_from_json(unit, ANOTHER_URL + value_type.val());
});
I wanted to:
Load the document
Get some JSON data from an associated database
Put the data in #value_type <select> item
Get the value of #value_type select, and query the database once again to populate another select item.
The problem is, when I call value_type.val(), it always outputs null, even though the #value_type <select> is correctly populated. What am I doing wrong here?
I suppose something like this may work better with promises.
Along these lines (untested):
var populate_select_from_json = function($select, json_url) {
$select.empty();
return $.getJSON(json_url, function(data) {
$.each(data, function(key, value) {
$("<option></option>")
.attr("value", value.name)
.text(value.title)
.appendTo($select);
});
$select.children(":first").attr("selected", true);
});
};
$(document).ready(function() {
var $value_type = $("#value_type");
var $unit = $("#unit");
populate_select_from_json($value_type, SOME_URL).done(function(){
populate_select_from_json($unit, ANOTHER_URL + $value_type.val());
});
});
Hi I am Working On a Web Form..
I Have A combo Box for holding all The Units.
I Have Taken All The units from the Database Using JSON,now i need to Bind All these Units To the drop down List
How can I Do this...?
function getUnitFamily(pack_detl_ID,select) {
//***********************************//
PageMethods.getUnitFamily(pack_detl_ID,
function(result) {
if (result != null) {
custinfo = eval(result);
if (custinfo != null) {
$('#<%=drpUnit.ClientID%> option').remove();
var objSub = document.getElementById('<%=drpUnit.ClientID%>');
$.each(custinfo, function(i, item) {
listOpt = document.createElement("option");
listOpt.value = item[0];
listOpt.text = item[1];
objSub.add(listOpt);
});
alert(select);
document.getElementById('<%= drpUnit.ClientID %>').value = select;
}
}
}, pageMethodError);
With An example can any one explain
A combobox sounds like you are using an ASP.NET control. Of course, you can bind your items to that control in the code behind. If you are doing some AJAX stuff and have a dropdown ( element>) in your page which you want to populate at client side, you might want to take a look at what jQuery has to offer. For example use the AJAX api to retrieve your data and push that data into your dropdown like so:
var options = $("#options");
$.each(result, function() {
options.append($("<option />").val("sometext").text("sometext"));
});
In the past I have used a plugin when working with dropdowns.
http://www.texotela.co.uk/code/jquery/select
Request the JSON data:
//Get the JSON Data
$.getJSON(url, function(json) {
PopulateDropDownFromJson(json, "#element");
});
and then just pass the JSON into a function that uses the plugin above
function PopulateDropDownFromJson(json, element){
$.each(json, function() {
$(element).addOption(this[valueText], this[displayText], false);
});
}