Hi,

With reference to the post : http://drupal.org/node/358356

I am having difficulty getting this piece of code to work. I am making a filter based system with select boxes. The first select shows the countries. When a country is selected it will create a new select box below it with all the provinces/states in it. You select a province/state and it will create a new select box that will show all the cities/towns.

Country -> Province/states -> City/Town -> suburbs

I have had a look at #ahah and that gives me what I need to create a new field on an event. The problem I have is that I need to somehow get the value that was selected in the country select box inorder to generate the province box.

Does anyone have an idea on how I can approuch this problem? Maybe some sample code?

Thanks in advance,
Davin

Comments

arcaneadam’s picture

I have been tackling the ahah form stuff this weekend. I used the pol and upload modules as a guide for how to accomplish what I wanted.

Here is how the poll module does it.

  1. User fills out a question and two responses.
  2. User clicks the add another response button
  3. the form submits via the ahah parameter
  4. Drupal calls the polls/js menu item
  5. poll_js gets the form cache using form_get_cacheI()
  6. poll_js proccess the form using drupal_proccess_form()
  7. The form function recognizes that there it needs to add another choice input and adds it.
  8. poll_js rebuilds the form using drupal_form_rebuild() then renders it using drupal_render()
  9. poll_js writes the rendered form to a json output to the page with drupal_json()
  10. Steps 4-10 all happen behind the scene and when complete the aha paramaters on the form tell it to load the results into a specified DOM element, which in poll modules case is the entire form wrapper.
  11. The new form with the added choice input is faded in over the old form and viola you have a completed aha function.

I hope that help explain how to do it a little.

Adam A. Gregory
_____________________________
Drupal Developer and Consultant
https://goo.gl/QSJjb2
Acquia Certified Developer-Back end Specialist

Trappies’s picture

Hey,

That works fine for the poll say, but, how do I pass the selected value from the first object(That is firing the event, in this case the Country field), to the next object that is to be created using that value? this being the province select box. See the poll creates a new field that gets a new name and thats about it, it never needs to be generated based on the previous poll. So when it gets submitted it submits all those new values.

I understand what you are explaining and you have it spot on but my problem is not getting solved, no matter which way I work it :(

Thanks for the response :)

Davin

Trappies’s picture

HA!

I have a partial solution and it works pretty well. :D All I basically did was to go check the $_POST values. This gave me the value I wanted to carry over. Works great!

Now the next part of this problem is to get this part to work "Province -> Town". How do I declare a field to have a #ahah function if it doesn't exist yet? I have tried doing the same as the original but that doesn't seem to be working. I also tried to make a hidden field so it could generate the JSON I think but that isn't working either. Anyone have any ideas for this?

Thanks in advance,
Davin

arcaneadam’s picture

In general Drupal discourages using $_POST to retrieve the various values of form and while there is nothing technically wrong with it it is better for coding standards to merge the $post results in your #ahah callback into $form_state['values'] using something like $form_state = array('values' => $_POST);

once you set the $form_state you could use a conditional in your form function some thing like this

function my_form($form_state){
  $form['country']=array(
    '#type'=>'select',
    '#options'=>$countries, //you would obviously populate this with your countries options
    '#default_value'=>(isset($form_state['values']['country']) ? $form_state['values']['country'] : 'USA'),
  );
  if(isset($form_state['values']['country'])){
     $provs = my_prov_func($form_state['values']['country']); //passes the country value to a function to get the prov. options
     $form['prov']=array(
       '#type'=>'select',
       '#options'=>$prov, //you would obviously populate this with your countries options
       '#default_value'=>(isset($form_state['values']['prov']) ? $form_state['values']['prov'] : $prov[0]),
     );

         if(isset($form_state['values']['prov'])){
            $towns= my_towns_func($form_state['values']['prov']); //passes the prov value to a function to get the town options
            $form['town']=array(
              '#type'=>'select',
              '#options'=>$towns, //you would obviously populate this with your countries options
              '#default_value'=>(isset($form_state['values']['town']) ? $form_state['values']['town'] : $towns[0]),
             );
        }
    }
}

You can just set the ahah callback and stuff the same for each element and have the callback merge the post values into $form_state then re-render the form with the $form_state set. It should then be able to iterate through a conditional similar to the above.

Adam A. Gregory
_____________________________
Drupal Developer and Consultant
https://goo.gl/QSJjb2
Acquia Certified Developer-Back end Specialist

Trappies’s picture

Hi arcaneadam,

I understand what you are getting at and it makes perfect sense. What I am having trouble getting my mind around is the actual taking of the form from the cache and then adding the new elements. It makes perfect sense. But in code I cannot get it working.

So what I understand is this.

1. The form is generated with only showing the country options.
2. This country field look something like this:

        $form['country']=array(
		'#type'=>'select',
		'#options'=>$countries, //you would obviously populate this with your countries options
		'#ahah' => array(
			'event' => 'change',
			'path' => 'mymodule/newfield_js',
			'method' => 'replace',
			'effect' => 'fade',
		),
		'#default_value'=>(isset($form_state['values']['country']) ? $form_state['values']['country'] : 'USA'),
	);

3. This will then just say rebuild the form and then the next field will be rendered based on your code above?

Does this make sense?

Thanks in advance,

Davin