0
votes

I have a question about cakePHP. I create two drop down lists in my view. When the user changes the value in one list, I want the second to change. Currently, I have this working like this: An on click event fires when the user selects from list box one. This fires a jQuery ajax function that calls a function from my controller. This is all working fine, but how do I re-render my control, asynchronously (or, view)? I i know I could just serialize the array to json and then recreate the control in javascript, but there seems like there should be a more "CakePHP" way. Isn't that what render is for? Any help would be great. Here's the code I have so far:

jQuery:

function changeRole(getId){

$.ajax({
    type: 'POST',
    url: 'ResponsibilitiesRoles/getCurrentResp',
    data:  { roleId: getId },
    cache: false,
    dataType: 'HTML',
    beforeSend: function(){
    },
    success: function (html){

    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {

    }

});

View:

<?php


echo 'Roles:';
    echo'<select name="myOptions" multiple="multiple">';
    foreach ($rolesResponsibility as $role) {
       echo' <option onclick="changeRole(this.value);"  value="';  echo $role["ResponsibilitiesRole"]["role_id"]; echo '">'; echo $role["r"]["role_name"]; echo '</option>';
    }
    echo '</select>';

echo 'Responsbility:';
echo'<select name="myOptionsResp" multiple="multiple">';
foreach ($respResponsibility as $responsibility) {
    echo' <option  value="';  echo $responsibility["responsibility"]["id"]; echo '">'; echo $responsibility["responsibility"]["responsibility_name"]; echo '</option>';
}
echo '</select>';

?>

Controller function:

public function getCurrentResp(){ $getId = $this->request->data['roleId'];

$responsibilityResp = $this->ResponsibilitiesRole->find('all',
    array("fields" => array('role.role_name','ResponsibilitiesRole.role_id','responsibility.*'),'joins' => array(
        array(
            'table' => 'responsibilities',
            'alias' => 'responsibility',
            'type' => 'left',
            'foreignKey' => false,
            'conditions'=> array('ResponsibilitiesRole.responsibility_id = responsibility.id')
        ),
        array(
            'table' => 'roles',
            'alias' => 'role',
            'type' => 'left',
            'foreignKey' => false,
            'conditions'=> array('ResponsibilitiesRole.role_id = role.id')
        )

    ),
        'conditions' => array ('ResponsibilitiesRole.role_id' => $getId),

    ));
$this->set('respResponsibility', $responsibilityResp);

//do something here to cause the control to be rendered, without have to refresh the whole page       

}
1
You could reload the page whenever the user changes the first dropdown list so that it displays the correct list for the second, or have cakePHP respond to the ajax call with a page that displays only the new control, and then when the ajax call returns, replace the old control with the one CakePHP responded with.Kai

1 Answers

1
votes
  • The js event is change fired on the select tag and NOT click
  • You can use the Form Helper to build your form.
  • Pay attention Naming things following the cakephp way.

Because your code is a bit confused i will make other simple example:

Country hasMany City
User belongsTo Country
User belongsTo City

ModelName/TableName (fields)
Country/countries (id, name, ....) 
City/cities (id, country_id, name, ....)
User/users (id, country_id, city_id, name, ....)

View/Users/add.ctp

<?php
    echo $this->Form->create('User');
    echo $this->Form->input('country_id');
    echo $this->Form->input('city_id');
    echo $this->Form->input('name');
    echo $this->Form->end('Submit');

    $this->Js->get('#UserCountryId')->event('change',
        $this->Js->request(
            array('controller' => 'countries', 'action' => 'get_cities'),
                array(
                    'update' => '#UserCityId',
                    'async' => true,
                    'type' => 'json',
                    'dataExpression' => true,
                    'evalScripts' => true,
                    'data' => $this->Js->serializeForm(array('isForm' => false, 'inline' => true)),
            )
        )
    );
    echo $this->Js->writeBuffer();

?>

UsersController.php / add:

public function add(){
    ...
    ...
    // populate selects with options
    $this->set('countries', $this->User->Country->find('list'));
    $this->set('cities', $this->User->City->find('list'));
}

CountriesController.php / get_cities:

public function get_cities(){
    Configure::write('debug', 0);
    $cities = array();
    if(isset($this->request->query['data']['User']['country_id'])){
        $cities = $this->Country->City->find('list', array(
                  'conditions' => array('City.country_id' => $this->request->query['data']['User']['country_id'])
        ));
    }
    $this->set('cities', $cities);
}

View/Cities/get_cities.ctp :

<?php 
    if(!empty($cities)){
        foreach ($cities as $id => $name) {
?>
<option value="<?php echo $id; ?>"><?php echo $name; ?></option>
<?php           
        }
    }
?>