1
votes

My business directory application calls for 3 chained select boxes, and I'm using cakephp to build this application.

The hierarchy and order of choices for the sections is this:

1 - business group

2 - business type

3 - city (included in table customer)

The relationships are:

  • customer HABTM business types

  • business groups have many business types

  • business types have one business group, HABTM customers

I have searched for jquery plugins that help with this, and found one by Remy Sharp, but it doesn't have the more complex relationships I have. http://remysharp.com/2007/09/18/auto-populate-multiple-select-boxes/

What I imagine happening is the first selection box (business groups) is pre-populated and once a selection is made, an event listener send a message that filters the second selection box, and the same for the third.

What I don't know is how to structure the search action based on the event listener.

Any advice or am I way off base?

As always, I come to the well for help.

Much appreciated. Paul


Thanks very much Nick, I've read many of your posts I really appreciate your response.

I've followed your instructions but have run into problems. I've tried my best to resolve them but haven't figured it out.

This is what I've done so far:

1) created 'chained' actions in both the business_type and business_directory (renamed customer to business directory, which is more appropriate.)

business type chained action:

function chained($business_group_id) {
    $business_types = $this->BusinessType->find('list', array(
        'conditions' => array( 'BusinessType.business_group_id' => $business_group_id)
        ));

         $this->set('business_types', $business_types);
     }

business directory chained action:

function chained($business_type_id) {
    $business_directories = $this->BusinessDirectory->bindModel(array( 'hasOne' => array('business_directories_business_types' )));         
    $business_directories = $this->BusinessDirectory->find('all', array(
        'fields' => array( ' BusinessDirectory.city'),
        'conditions' => array( 'business_directories_business_types.business_type_id' => $business_type_id)
        ));
            $this->set('business_directories', $business_directories);
     }

I did find that with a HABTM relationship, using find 'list' didn't create the join query, whereas find 'all' did.

2) I then created a search action in the business directory and corresponding view.

For the business groups I created a getList action to populate the option list in the search form:

function getList() {
     return $this->BusinessGroup->find('list');
}

In the search view, I've added the javascript for the chain select:

<script type="text/javascript">
<!--
$(function () {
    var group = $('#businessGoup');
    var type = $('#businessType');
    var city = $('#businessDirectoryCity');

    type.selectChain({
        target: city,
        url:  '../business_directories/chained/'+$(this).val(),
  data: { ajax: true, anotherval: "anotherAction" }
    });

    group.selectChain({
        target: type,
        url: '../business_types/chained/'+$(this).val()   
    }).trigger('change');

});
//-->
</script>

And the form:

create('business_directories', array('action'=>'/search_results')); ?> input('business_group_id', array( 'type' => 'select', 'id' => 'businessGoup', 'empty' => '-- Select Business Group --', 'multiple' => true, 'options' => $this->requestAction('/business_groups/getList' ), 'label' => 'Business Group')); ?> input('business_type.id', array( 'type' => 'select', 'id' => 'businessType', 'empty' => '-- Select Business Type --', 'multiple' => true, 'options' => 'none selected', 'label' => 'Business Type')); ?> input('business_directories.id', array( 'type' => 'select', 'id' => 'businessDirectoryCity', 'empty' => '-- Select City --', 'multiple' => true, 'options' => 'options', 'label' => 'City')); ?> end('Search'); ?>

When I test the business type chain function, /business_types/chained/1, everything works.

But when I test the search view, I get a javascript alert error. Then when I check firebug, I get the following two errors:

Warning (2): Missing argument 1 for BusinessTypesController::chained() [APP\controllers\business_types_controller.php, line 71]

Notice (8): Undefined variable: business_group_id [APP\controllers\business_types_controller.php, line 73]

Any additional help with this is very much appreciated.

Thanks, Paul

1
Look like you didn't pass the variables in the action. i.e. function chained($business_group_id) doesn't have the parameter $business_group_id and the second error is subsequent. With firebug check what is the url triggered after the selecting an element. I believe it will be something like: /business_directories/chained/undefined. There are very bad practices in your code, but I wont discuss them. But for sure try to replace the requestAction with regular variable from the controller. After all it's a list. I hope you convert the response as properly formatted string, as the demo shows. - Nik Chankov

1 Answers

2
votes

What you need is to have 2 actions in the controllers (business_type and customer).

each action should look like this. In that case for the business type

function chained($parent_id){
    $business_types = $this->BusinessType->find('list', array('conditions'=>'BusinessType.business_group_id'=>$parent_id));
    $this->set('business_types', $business_types);
}

of course you need also view for that action which will format the values in the proper format for the chained select.

For Business group you need to show all values directly so no ajax is needed.

The Customer controller's action is similar, but you need to select cities of all related customers.

Then with the chained select you need to set the proper elements and set the proper actions which need to be called.

i.e.:

$('#id-of-the-business-group').selectChain({
    target: $('#id-of-the-business-type-field'),
    url: '/business_types/chained/'+$(this).val()
});