I've ran into a problem in my Geb tests where I'm trying to hit a select dropdown box where the first option is null (user wanted it to display blank as the first option). It is a state field as follows. Note that the original html has an empty array for the from value. The state gets filled based on the selection of "USA" as country based on an Ajax call, I've had to edit it a bit.
How do I set my selector to hit the second or third value? Can I pass values into the selector as an array or something similar? "100225" the value for USA in both the Firebug HTML and my testing db xml, and "102722" is the state value for "Alabama"
***What I'm trying to achieve is this: I want to be able to hit one of the unique state values such as 102722 but Geb only hits the very first value which is always null in the select box, although the '102722' value exists both in the Firebug HTML and in my test xml db so I know its there. As you can see, I've written the Geb selector for State several different ways. This is the error that always comes back:
| java.lang.IllegalArgumentException: couldn't select option with text or value: 102722
NOTE: Also note below that a println of the value in Geb always returns a null value.
Original form item:
<div class="col-sm-3">
<label id="Country-label" class="toplabel" for="Country">Country<span class="required-indicator">*</span></label>
<g:select name="Country" id="Country" from="${dbinfo...Country.list().sort{it.orderNumber}}" class="form-control" required="" optionKey="id" value="${Instance.Country}" aria-labelledby="Country-label"/>
</div>
<div class="col-sm-2">
<label id="State-label" class="toplabel" for=State>State<span id="StateAsterisk" class="required-indicator">*</span></label>
<g:select name="State" id="State" from="${[]}" class="form-control" optionKey="id" value="${...Instance.State}" noSelection="['null':'']" aria-labelledby="State-label"/>
</div>
Rendered HTML from Firebug:
<select id="Country" class="form-control" aria-labelledby="Country-label" required="" name="Country">
<option selected="selected" value="100225">United States</option>
<select aria-labelledby="State-label" class="form-control" id="State" name="State">
<option value="null"></option>
<option value="102722">Alabama</option>
<option value="102723">Alaska</option>
Geb selector excerpt from test:
println $('#Country').value()
waitFor(5){$('#Country').click()}
$('#Country').value(100225) // USA
waitFor(10){$('#Country').find("option").find{ it.value() == 100225 }.click()} // USA
println $('#State').value() // --> RETURNS NULL VALUE
$('#State').find("option").find{ it.value() == 102722}.click() // --> NONE OF THESE WILL HIT
waitFor(5){$('#State').click()} // --> NONE OF THESE WILL HIT
waitFor(5){$('#State').value(102722)} // --> NONE OF THESE WILL HIT
Javascript/Ajax call - that loads states based on country USA:
$(document).ready(function(){
$('#Country').change(function() {
var country = $(this).val();
if(country != null && country != 'null'){
loadStates(country, null, 'submitter', true);
}
});
<g:if test="${...Country}">
$('#Country').val(${...Country});
loadStates(${...Country}, "${...State?:null}", 'submitter', true);
</g:if>
var xhr = null;
function loadStates(country, state, selectId, hideShowAsterisk){
if(xhr != null){
xhr.abort();
xhr = null;
}
xhr = $.ajax({
url: '${request.contextPath}.../aj/loadStatesByCountry',
data: { country: country, selectId:selectId },
async:false,
success: function(data) {
$('#'+selectId+'State').html(data);
$('#'+selectId+'State-label').show();
if(state){
$('#'+selectId+'State').val(state);
}
if(hideShowAsterisk){
if(country == ${grailsApplication....country.usa}){
$('#'+selectId+'StateAsterisk').show();
}else{
$('#'+selectId+'StateAsterisk').hide();
}
}
xhr = null;
},
error:function(jqXHR, textStatus){
if(textStatus != 'abort'){
xhr = null;
alert("There was an error requesting the States for the selected Country");
}
}
});
}
Did you try the following:
waitFor(30){$("form").State = "102722"}
Related
Sir, my ajax isnt loading when i use select2 plugin .
it works fine when i remove it. the blur event is working.
but i want to be able to search in the dropdown, and somehow ajax isnt working
this part isnt working
$("#bank_id").focus();
so due to above script not working the blur event in the code below isnt working.
this is the script and html
<div class="col-md-6">
<div class="form-group">
<label>Bank<span><font color="red"></font></span></label>
<select class="form-control select2" name="bank_id" id="bank_id">
<c:choose>
<c:when test="${bankDetailsEdit.bank_id != 0}">
<option value="${bankDetailsEdit.bank_id }" >${bankDetailsEdit.bankName }</option>
</c:when>
<c:when test="${bankDetailsEdit.bank_id == 0}">
<option disabled selected>Select Bank</option>
</c:when>
</c:choose>
<c:forEach var="bank" items="${bankMasterDetails}">
<option value="${bank.bank_id}">${bank.bank_name}</option>
</c:forEach>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Bank Branch Name<span><font color="red"> </font></span></label>
<select class="form-control select2" name="bankBranchId" id="op1" >
<option value="${bankDetailsEdit.bankBranchId }" >${bankDetailsEdit.bankBranchName }</option>
<c:forEach begin="0" end="100" varStatus="loop">
<option></option>
</c:forEach>
</select>
</div>
</div>
<script>
$('.select2').select2();
$(document).ready(function(){ /* PREPARE THE SCRIPT */
$("#bank_id").focus();
$("#bank_id").on('blur change',function(){ /* WHEN YOU CHANGE AND SELECT FROM THE SELECT FIELD */
var bank_id = $(this).val(); /* GET THE VALUE OF THE SELECTED DATA */
var dataString={'bank_id':bank_id}; /* STORE THAT TO A DATA STRING */
$.ajax({
type: "GET",
url: "${pageContext.request.contextPath}/broker/bankBranchDetails",
data : ({
'bank_id':bank_id
}),
success: function (bankList) {
$('#op1').empty();
var opt = '<option disabled selected>Select Branch</option>';
for (var i = 0; i < bankList.length; i++) {
$('#op1').append(opt);
opt = new Option(bankList[i].bank_branch_name,bankList[i].bank_branch_id);
}
},
error: function (request, error) {
alert("Unable to fetch bank details");
}
});
});
$("#op1").change(function(){ /* WHEN YOU CHANGE AND SELECT FROM THE SELECT FIELD */
var branch_id = $(this).val(); /* GET THE VALUE OF THE SELECTED DATA */
var dataString={'branch_id':branch_id}; /* STORE THAT TO A DATA STRING */
$.ajax({
type: "GET",
url: "${pageContext.request.contextPath}/broker/branchIfscDetails",
data : ({
'branch_id':branch_id
}),
success: function (data) {
var ifsc = data;
document.getElementById("ifsc").value=ifsc;
},
error: function (request, error) {
alert("Unable to fetch bank details");
}
});
});
});
</script>
From this page: https://select2.org/programmatic-control/events:
Select2 has an internal event system that works independently of the
DOM event system, allowing adapters to communicate with each other.
You are tied to using the plugins event handling mechanism so the first paremeter of the jQuery on function needs to be changed.
from $("#bank_id").on('blur change',function(){
to $("#bank_id").on('select2:select',function(){
Unfortunately $("#bank_id").focus(); will not work because it is not listed in the available select2 events.
You're success callback function in the first event listener, which tries to generate options element for the 2nd select box will also not work as select2 has a different way of adding options dynamically through AJAX as listed in this page: https://select2.org/data-sources/ajax
You need to use $('#bank_id').select2('open'); instead of $("#bank_id").focus(); to open the bank selection on page load.
You can check their documentation.
CURRENT: Dropdown choice of 'Yes/No'.
'Yes' = Show 'additional' dropdown/inputs to be entered
'No' = Hide 'additional' dropdown/inputs
WANT: I want to make it so if the user chooses 'Yes', then enters something into the 'additional' dropdowns/inputs, but then decides to switch their original answer back to 'No', make it clear the 'additional' values.
This is so when the form submits, i wont be carrying over any values in the POST that aren't needed.
HTML
<section><style>.required {color:#ff0000;font-weight:bold;position:absolute;}</style>
<div class="section_header">LNB INFORMATION</div>
<label>Did you install an LNB?<span class="required">*</span> </label>
<select class="DropdownClass" name="lnb_choice" id="lnb">
<option disabled selected value="">Select... (Required)</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
<br>
<div class="LNBChoice DivElement1">
<select class="DropdownClass qrt" name="lnb_type" id="lnb_type">
<option value="">Type...</option>
<option value="3D2RBLNB">REV 3 LNB</option>
<option value="5D2RBLNB">REV 5 LNB</option>
<option value="SL3S4NR2">SWM3 LNB</option>
<option value="SL5S4NR2">SWM5 LNB</option>
<option value="SL5K4NR1">KAKU LNB</option>
</select>
<input type="text" id="lnb_barcode" name="lnb_barcode" placeholder="LNB Serial..." class="scantype basic" />
</div>
</section>
JS + Jquery 1.10.1
$(".DropdownClass").change(function () {
if ($(this).attr('name') == 'lnb_choice') {
var number = $(this).val();
$('.LNBChoice').hide().slice( 0, number ).show();
}
});
JSFIDDLE: https://jsfiddle.net/ra1t9jfL/
Additional issue: This is all part of a ,
If there is an error, i return them back to this page, using &field=value on the url to return values to the corresponding text input boxes/dropdowns.
I am able to return the 'Yes' value to the dropbox, but it does not activate the 'Show additional jquery'.
So the user has to select, 'No' then back to 'Yes' for the 'additional' to show up.
Add these two lines before or after $('.LNBChoice').hide().slice( 0, number ).show();
$('#lnb_type').val('');
$('#lnb_barcode').val('');
To clear the additional fields when the user selects "No" from the first drop down, you can add this which will do that:
$('#lnb').change(function() {
if($(this).val() === '0') {
/* User selected "no" so reset the additional field values */
$('#lnb_type').val('');
$('#lnb_barcode').val('');
}
});
To initialise the form based on values passed from the query string of the URL (ie on return from error screen), you could take the following approach:
/* Add the following script to your page */
$(function() {
/*
Access query string of url, remove preceding "?", and split
query string by "&" to return an array of "field=value" sub-strings
if any exist. Iterate the array of these sub-strings with forEach
*/
location.search.slice(1).split('&').forEach(function(part){
/* Split current sub-string by "=" to obtain name and value */
var nameValue = part.split('=');
var name = nameValue[0];
var value = value[1];
/* Select form element by name and initialise the value */
$('[name="' + name + '"]').val(value);
});
});
Basically i have a select dropdown
<select class="form-control" id="ursel"
ng-change="changeVal()"
ng-options="a for a in RatedVoltage" data-ng-model="TechCharacters.selectedUr">
<option value="" selected="selected">{{globalLangResource.SelectAny}}</option>
</select>
So on change of this select, have results reflecting to another select
viewModel.changeVal = function(){
var val = viewModel.TechCharacters.selectedUr;
if (val != undefined && val === "7.2kV") {
$rootScope.ud = viewModel.InsulationVoltage["7.2kV"]; // 20,30,40
}
}
The 2nd dropdown looks like this
<select class="form-control" id="udsel"
ng-change="setUd();"
ng-options="a for a in ud" data-ng-model="TechCharacters.InsulVolt">
<option value="" ng-if="false"></option>
</select>
Now i have a submit button, on submit,i am getting the main object.
console.log(TechCharacters);
Here i am not getting TechCharacters.InsulVolt value. it is showing empty.
If i have made change is the 2nd dropdown, the model is updated. until then i am not getting the changed model from 1st dropdown
Basically i want all the ng-model values inside form even it is changed or not.
if you want the first object of second dropdown on change of first one. change code to .
viewModel.changeVal = function(){
var val = viewModel.TechCharacters.selectedUr;
if (val != undefined && val === "7.2kV") {
$rootScope.ud = viewModel.InsulationVoltage["7.2kV"]; // 20,30,40
viewModel.TechCharacters.InsulVolt=$rootScope.ud[0]
}
}
hope it will help you
You can actually do this. This will work.
<select data-ng-model="TechCharacters.selectedUr"
<option ng-selected="{{obj == TechCharacters.selectedUr}}" value="{{obj}}" ng-repeat="(key,value) in RatedVoltage">
</select>
Basically you are doing ng-selected and comparing the ng-model value with that of the ng repeat value, and the selected value will be shown.
I have 3 select dropdown fields Country,State,City.Onload of the page only country field is enabled (city and state fields are disabled)then if user select country then state field is enabled(with all the states mapped on that country stored in my database) then if user select state then city field is enabled(with all the city mapped on the on that state stored in my database).My dropdowns code are
<select class="form-login" id="country_id" onchange="setDropdownState();">
<option value="select" >Select country</option>
#for(country <- countryList) {
<option value="#country.getId" >#country.getName</option>
}
</select>
<select class="form-login" id="state_id" onchange="setDropdownCity();">
<option value="select" >Select country</option>
#for(state<- Country.findStateByCountryId(get value of cid from setDropdownState function)) {
<option value="#state.getId" >#state.getName</option>
}
</select>
<select class="form-login" id="city_id" >
<option value="select" >Select country</option>
#for(city<- State.findCityByStateId(get value of sid from setDropdownCity function)) {
<option value="#state.getId" >#state.getName</option>
}
</select>
scripts
$(document).ready(function() {
$("#state_id").attr("disabled", true);
$("#city_id").attr("disabled", true);
});
function setDropdownState() {
var cid = $("#country_id").val();
if (cid != "select") {
//pass value to state dropdown
$("#state_id").attr("disabled", false);
} else {
$("#state_id").attr("disabled", true);
$("#city_id").attr("disabled", true);
}
}
function setDropdownCity() {
var sid = $("#state_id").val();
if (sid != "select") {
//pass value to citydropdown
$("#city_id").attr("disabled", false);
} else {
$("#city_id").attr("disabled", true);
}
}
So I have to pass country_id value onchange of country select box to get state field for loop value Country.findStateByCountryId(get value of cid from setDropdownState function) and in the same way pass state_id on change of state field to city field for loop to get the desired city on that particular state State.findCityByStateId(get value of sid from setDropdownCity function).
So how can I pass javascript value to model??
Is It possible??
Or is there any other way to do this??
Thanks
I think this link will help you out. http://jsfiddle.net/bdhacker/eRv2W/ It's a very similar situation that comes from this site https://bdhacker.wordpress.com/2009/11/21/adding-dropdown-country-state-list-dynamically-into-your-html-form-by-javascript/
Basically they create an event listener that listens for a change in the first dropdown menu, and then calls a function that passes that information into the second dropdown. It looks like this
countryElement.onchange = function () {
populateStates(countryElementId, stateElementId);
};
I have this show/hide div. And I am running into couple issues. I am using CodeIgniter by the way.
First : When I select real-estate the div shows. But if I select Service, the real-estate div won't hide. (Service has no div).
Second : If I select real-estate and fill out the form, and I change my mind and select automobile and fill out the form then send to database, I get all the fields from real-estate and automobile into my database. Which is not what I want.
Third : Is there a different approach if I wanna add more categories and more divs show/hide?
<select id="catid_1" name="catid_1">
<option value=""></option>
<option value="5">Real-Estate</option>
<option value="8">Automobile</option>
<option value="10">Service</option>
</select>
<!--Auto-->
<div id="8" class="forms">
Energie :
<select name="energy">
<option></option>
<option value="Gasoline">Gasoline</option>
<option value="Diesel">Diesel</option>
<option value="GPL">GPL</option>
<option value="Electric">Electric</option>
<option value="Hybrid">Hybrid</option>
</select><br />
Transmission :
<select name="tans">
<option></option>
<option value="Manuel">Manuel</option>
<option value="Automatic">Automatic</option>
</select><br />
Miles :
<input type="text" name="mile"/><br />
Year :
<input type="text" name="year"/><br />
</div>
<!--Realestate-->
<div id="5" class="forms">
Room :
<input type="text" name="room"/><br />
Surface :
<input type="text" name="surface"/><br />
</div>
<!--End Tech-->
$(function() {
$(".forms").hide();
$("#catid_1").change(function() {
var e = $(this).val();
if(e == '8' || e == '5') {
$(".forms").hide().parent().find('#' + e).show().addClass('form-active');
}
});
// Bind to the submit
$('#submit').click(function(e){
e.preventDefault();
// Parse the data only for the displayed div.
var resolve_data = function() {
var output = {};
// Here you place the acceptable fields.
$('.form-active input, .default input').each(function() {
output[$(this).attr('name')] = $(this).val();
});
return output;
};
// Submit the form here.
$.ajax({
url: '/echo/json/',
type: 'POST',
dataType: 'json',
data: resolve_data(),
beforeSend: function(xhr, settings){
// Before sending, check the data.
alert(settings.data);
},
complete: function(xhr, textStatus) {
//called when complete
},
success: function(data, textStatus, xhr) {
//called when successful
},
error: function(xhr, textStatus, errorThrown) {
//called when there is an error
}
});
});
});
first: service show/hide is not working because you're putting a conditional on the ID:
if(e == '8' || e == '5') { // <<-- remove this conditional
$(".forms").hide().parent().find('#' + e).show().addClass('form-active');
}
second: When you're doing your update, check the value of the drop down box and only update the fields that belong to that choice. Your form should be sending along the value of the option, so that's not to hard to do. For instance, if the select value is 5, only update the room and surface fields in your database. Don't try to clear the form when switching choices, it's safer to do this in the back end.
If you insist on doing it front end, put an actual form in there and .reset() it when changing options.
third: probably, but this seems OK no? Are you not happy with it?
http://jsfiddle.net/zf9BN/1/