gravity forms : use previous dropdown choice as variable in gform_pre_render?
This question is mainly regarding [[LINK href="http://www.gravityhelp.com/documentation/page/Gform_pre_render"]]gform_pre_render[[/LINK]] which I am using in my functions.php pre-render 2 dropdowns, but applying some conditional logic manually to Dropdown B.
In a nutshell, I have dealer form. Which basically you choose your county, and then your dealer.
<strong>Dropdown A = Dealer Country</strong>
<strong>Dropdown B = Dealer Name</strong> // this will be hidden by conditional logic until Dropdown A is chosen.
I have about 15 countries, and I am using get_terms in this first gform_pre_render function to list all my countries that I have assigned to a dealer post, quite straight forward...
// Dropdown A - Dealer Country
add_filter("gform_pre_render", "dropdown_dealer_country");
add_filter("gform_admin_pre_render", "dropdown_dealer_country");
function dropdown_dealer_country($form){
if($form["id"] != 3)
return $form;
$terms = get_terms("dealer-country");
$items = array();
$items[] = array( "text" => __('Select country...','mission-theme'), "value" => 0 );
foreach($terms as $term)
$items[] = array( "text" => $term->name, "value" => $term->slug );
foreach($form["fields"] as &$field)
if($field["id"] == 6){
$field["choices"] = $items;
}
return $form;
}
OK so the above function works perfectly in Dropdown A.
Now what I am doing in Dropdown B is displaying all my dealer names (post titles) from my dealer post-type.
I have named each dealer custom post title with the name of the dealer, and this is what I am pre-populating Dropdown B with...
// Dropdown B - Dealer Name
add_filter("gform_pre_render", "dropdown_dealer_name");
add_filter("gform_admin_pre_render", "dropdown_dealer_name");
function dropdown_dealer_name($form){
if($form["id"] != 3)
return $form;
$dealers = get_posts(array(
"post_type" => "dealer",
"dealer-country" => $dealerCounty,
"post_status" => "publish",
"orderby" => "title",
"order" => "ASC",
"posts_per_page" => -1
));
$items = array();
$items[] = array( "text" => __('Select dealer...','mission-theme'), "value" => 0 );
foreach($dealers as $dealer)
$items[] = array( "text" => $dealer->post_title, "value" => $dealer->post_name );
foreach($form["fields"] as &$field)
if($field["id"] == 7){
$field["choices"] = $items;
}
return $form;
}
...and as you can see in line 11, I have a variable in my get_posts array <strong>"dealer-country" => $dealerCounty</strong>
My question, is it some how posible to get the choice that is made in <strong>Dropdown A</strong> into my $dealerCounty variable in my <strong>Dropdown B</strong> function?
Any tips or help would be much appreciated as my <strong>Dropdown B</strong> is currently very long, and I need to filter it down by country.
Many Thanks
Josh
Christianto answers:
Hi Josh,
If only GravityForm has options to set class for each choice (option)...
but we can re-populate all options for dealer name with ajax based on selected county
try this on functions.php,
[[LINK href="http://pastebin.com/vaeubLgz"]]http://pastebin.com/vaeubLgz[[/LINK]]
and ajax for getting post name/title based on county:
[[LINK href="http://pastebin.com/JTkmTrUV"]]http://pastebin.com/JTkmTrUV[[/LINK]]
we need to add class on gform_pre_render for our javascript function to both county and dealer name field,
for example on above code I use 'dealer-county' for county and 'dealer-name' for dealer name;
from the documentation add "cssClass" property to the field ( $field["cssClass"] )
// Dropdown A - Dealer Country
add_filter("gform_pre_render", "dropdown_dealer_country");
add_filter("gform_admin_pre_render", "dropdown_dealer_country");
function dropdown_dealer_country($form){
if($form["id"] != 3)
return $form;
$terms = get_terms("dealer-country");
$items = array();
$items[] = array( "text" => __('Select country...','mission-theme'), "value" => 0 );
foreach($terms as $term)
$items[] = array( "text" => $term->name, "value" => $term->slug );
foreach($form["fields"] as &$field){
if($field["id"] == 6){
$field["cssClass"] = 'dealer-county';
$field["choices"] = $items;
}
}
return $form;
}
and for dealer name, I think we don't need specific $dealerCounty category here, so we can populate all or none (since this field will be disable before county selected);
// Dropdown B - Dealer Name
add_filter("gform_pre_render", "dropdown_dealer_name");
add_filter("gform_admin_pre_render", "dropdown_dealer_name");
function dropdown_dealer_name($form){
if($form["id"] != 3)
return $form;
$dealers = get_posts(array(
"post_type" => "dealer",
"post_status" => "publish",
"orderby" => "title",
"order" => "ASC",
"posts_per_page" => -1
));
$items = array();
$items[] = array( "text" => __('Select dealer...','mission-theme'), "value" => 0 );
foreach($dealers as $dealer)
$items[] = array( "text" => $dealer->post_title, "value" => $dealer->post_name );
foreach($form["fields"] as &$field){
if($field["id"] == 7){
$field["cssClass"] = 'dealer-name';
$field["choices"] = $items;
}
}
return $form;
}
Josh Cranwell comments:
Hello, Christianto.
Thanks for for your clever response, I can see what your doing and it is great.
Thought I can't get it it to work, and I've checked the code as far to my ability.
Please see gist which include all the code... [[LINK href="https://gist.github.com/4663253"]]https://gist.github.com/4663253[[/LINK]]
[[LINK href="http://motocomdigital.co.uk/question7940.txt"]]Download raw txt code here[[/LINK]]
I've triple checked all classes and variables. This time it should read country not county. But I have updated everything.
From what I can see in the source, this is what is being outputted in the source...
<ul id="gform_fields_3" class="gform_fields top_label description_below">
<li id="field_3_6" class="gfield dealer-country gfield_contains_required">
<label class="gfield_label" for="input_3_6">Dealer country<span class="gfield_required">*</span></label>
<div class="ginput_container">
<select name="input_6" id="input_3_6" class="medium gfield_select" tabindex="5">
<option value="Select country...">Select country...</option>
<option value="england">England</option>
<option value="northern-ireland">Northern Ireland</option>
<option value="republic-of-ireland">Republic of Ireland</option>
<option value="scotland">Scotland</option>
<option value="wales">Wales</option>
</select>
</div>
</li>
<li id="field_3_7" class="gfield dealer-name" disabled="disabled">
<label class="gfield_label" for="input_3_7">Dealer</label>
<div class="ginput_container">
<select name="input_7" id="input_3_7" class="medium gfield_select" tabindex="6">
<option value="Select dealer...">Select dealer...</option>
<option value="dealer-name-1">Delear Name 1</option>
<option value="dealer-name-2">Delear Name 2</option>
<option value="dealer-name-3">Delear Name 3</option>
<option value="dealer-name-4">Delear Name 4</option>
<option value="dealer-name-5">Delear Name 5</option>
<option value="dealer-name-6">Delear Name 6</option>
<option value="dealer-name-7">Delear Name 7</option>
...
</select>
</div>
</li>
</ul>
Can you help me fix the problem? I have added more funds.
From what I can see, even though i've specified 0 as the value in...
$items[] = array( "text" => __('Select country...','mission-theme'), "value" => 0 );
It is outputting...
<option value="Select country...">Select country...</option>
And also I've noticed the disabled="disabled" is being added to the li and not the dropdown itself?
Josh Cranwell comments:
I just figured it out...
$items[] = array( "text" => __('Select country...','mission-theme'), "value" => "default" );
which now outputs...
<option value="default">Select country...</option>
then your script was not finding the select element, but instead the containing li, so I adjusted below to find the select...
<script type="text/javascript">
jQuery(document).ready(function($) {
var countryClass = '.dealer-country',
dealerClass = '.dealer-name';
// disable dealer name before county county selected
$(dealerClass).attr('disabled','disabled');
$(countryClass).change(function(){
var countrySelect = $(this).find('select'),
country = countrySelect.val(),
dealerSelect = countrySelect.parents('form').find(dealerClass + ' select');
if(country != "default"){
dealerSelect.attr('disabled','disabled');
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
data: { dealerCountry : country, action: 'get_dealer_name' },
success: function(data){
dealerSelect.empty();
var options = $.parseJSON(data);
for(i=0;i<options.length;i++){
dealerSelect.append('<option value="'+options[i].value+'">'+options[i].text+'</option>');
}
dealerSelect.removeAttr('disabled');
}
});
} else {
dealerSelect.attr('disabled','disabled');
$('option',dealerSelect).removeAttr('selected');
}
});
});
</script>
Again, many thanks for your help. :-)
Josh Cranwell comments:
Awesome!
Christianto comments:
target class for both country and dealer name on GForm is not directly refer to <select> element..
please change the class variable for county and dealer name :
var countyClass = '.dealer-country select',
dealerClass = '.dealer-name select';
I think the property can only receive string, if we change 0 to '0', is it still displaying text instead of value?
Please check this code:
[[LINK href="https://gist.github.com/4663590"]]https://gist.github.com/4663590[[/LINK]]
Christianto comments:
You're welcome :)
Glad you've resolved it..
Josh Cranwell comments:
Sorry I forgot to pay you,
Though I've found a slight bug. When my form submits, it appears to send the correct result.
But in admin the result given is always the very first dealer in the list.
It's not the first dealer in the overall list, its the first dealer in the country selected.
Very odd, not sure why thats happening :/
Josh Cranwell comments:
Actually no bug, was something I was trying to do in the get_post query.
I dont have one small question with the script, if you know a way.
Currently I am wrapping your script into a function...
countryFilter = function () {
var countryClass = '.dealer-country select',
dealerClass = '.dealer-name select';
// disable dealer name before county county selected
// $(dealerClass).attr('disabled','disabled');
$(countryClass).change(function(){
var countrySelect = $(this),
country = countrySelect.val(),
dealerSelect = countrySelect.parents('form').find(dealerClass);
if(country != "default") {
// dealerSelect.attr('disabled','disabled');
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
data: { dealerCountry : country, action: 'get_dealer_name' },
success: function(data){
dealerSelect.empty();
var options = $.parseJSON(data);
for(i=0;i<options.length;i++){
dealerSelect.append('<option value="'+options[i].value+'">'+options[i].text+'</option>');
}
dealerSelect.removeAttr('disabled');
}
});
} else {
// dealerSelect.attr('disabled','disabled');
// $('option',dealerSelect).removeAttr('selected');
}
});
}
and then running this like this...
countryFilter();
But I am also running the countryFilter(); in the post render like this which works nice.
$(document).bind('gform_post_render', function(event, form_id){
if(form_id == 3) {
countryFilter();
doTop(0);
}
});
My question is, can I keep the value on the the dealer drowndown if the there is an error on the form?
The dealer country stays on the selected item which is great, how ever the dealer down resets back to 'default'.
Also, I dont suppose you know a way or making...
$items[] = array( "text" => __('Select country...','mission-theme'), "value" => "default" );
...a non selectable item. So if my field is set to <strong>Field Required</strong>, how can I stop this from being a choice?
I have paid you now for help thanks again.
Kyle answers:
Are you looking to have this done without reloading the page? (i.e. ajax) Or are you breaking it up into two pages
Kyle comments:
For the multi-page solution I believe this tutorial will get the job done:
http://wpsmith.net/2012/plugins/how-to-pre-populate-a-radio-select-field-in-gravity-forms-based-on-previous-inputs/#gf_14
That uses a text input to search and pre-populate radio choices, so you will simpy adjust to use your dropdown input and pre-populate the second drop down. Don't forget to put your cpt in place of his too. Let me know if this helps.
Josh Cranwell comments:
Ideally, on the same page. Perhaps with a jquery script or something?
Francisco Javier Carazo Gil answers:
Josh,
Maybe an idea is reload only content of Dropdown B with an AJAX call as Kyle says.
But this would not be my idea. I would do my own form in this case and I will use AJAX easier.
1) Create a template with forms for this case
2) Create a page with an slug to be called
3) Include an AJAX call to fill it:
<script type="text/javascript" >
function populate_select()
{
$(function(){
$('#country2').change(function(){
var $tmp_Country2=$('#country2').val();
alert($tmp_Country2);
$("#city").empty();
$.ajax({
url:"/ROOT_TO_PHP_THAT_GENERATE_NEW_SELECT.php",
type:'POST', data:'country=' + $tmp_Country2,
success:function(results)
{
$("#city").removeAttr("disabled");
$("#city").append(results);
}
});
}
);
});
}
</script>
Josh Cranwell comments:
Many thank your for answer Francisco.
But I used Christianto's method below.