Tim Sanders
Tim Sanders

Reputation: 851

jQuery autocomplete widget in Cakephp Edit action

Problem: I have a jQuery script working in the add method of my controller, but when I add search functionality to the edit method the drop down menu does not work; however I know the jQuery script is working because I'm getting a response back with the results. I'm probably overlooking something simple, but I can't seem to spot it.

Controller Edit Method:

public function edit($id = null) {
            $this->loadModel('PsychproScreening');
            $this->set('pidList', $this->PsychproScreening->find('list', array('fields' => array('pid','pid'), 
                                                        'order' => 'pid ASC')));

    if (!$this->PsychproConcomitantMed->exists($id)) {
        throw new NotFoundException(__('Invalid psychpro concomitant med'));
    }
    if ($this->request->is('post') || $this->request->is('put')) {
        if ($this->PsychproConcomitantMed->save($this->request->data)) {
            $this->Session->setFlash(__('The psychpro concomitant med has been saved'));
            $this->redirect(array('action' => 'index'));
        } else {
            $this->Session->setFlash(__('The psychpro concomitant med could not be saved. Please, try again.'));
        }
    } else if(!$this->RequestHandler->isAjax()) {
        $options = array('conditions' => array('PsychproConcomitantMed.' . $this->PsychproConcomitantMed->primaryKey => $id));
        $this->request->data = $this->PsychproConcomitantMed->find('first', $options);
    }

            if ( $this->RequestHandler->isAjax() ) {
                debug('here');
                $this->search();
    }
}

Controller Search Method:

private function search(){
    $this->loadModel('FdaMed');
    $this->autoRender=false;
    $meds=$this->FdaMed->find('all',array('fields' => array('med_id','non_proprietary_name', 'route_name', 'dosage_for_mname'), 
                                'conditions'=>array('FdaMed.non_proprietary_name LIKE'=>'%'.$_GET['term'].'%')));
            $i=0;
            foreach($meds as $meds){
                    $response[$i]['value']=$meds['FdaMed']['med_id'];
                    $response[$i]['label']=$meds['FdaMed']['non_proprietary_name'].' ('.
                            $meds['FdaMed']['route_name'].'/ '.$meds['FdaMed']['dosage_for_mname'].')';
            $i++;
            }
    echo json_encode($response);
}

Edit View

<?php include_once 'concomitant_meds_inc.php';
$this->Html->addCrumb('PsychPro', '/Psychpros');
$this->Html->addCrumb('PsychPro Concomitant Med', '/PsychproConcomitantMeds');
$this->Html->addCrumb('Edit Concomitant Med', '/PsychproConcomitantMeds/edit/'.$this->request->data['PsychproConcomitantMed']['id']);
?>
<div class="psychproConcomitantMeds form">
<?php echo $this->Form->create('PsychproConcomitantMed',array('action' => 'edit')); ?>
    <fieldset>
        <legend><?php echo __('Edit Psychpro Concomitant Med'); ?></legend>
    <?php
        echo $this->Form->input('pid', array('options' => $pidList, 'empty' => 'Choose a value'));
                echo $this->Form->input('timept', array('options' => $tpt, 'empty' => 'Choose a value'));
                echo '<h3>Current Medication: '.$this->request->data['PidConcomitantMed']['non_proprietary_name'].' Route: '.
                        $this->request->data['PidConcomitantMed']['route_name']." Dosage Type: ".
                        $this->request->data['PidConcomitantMed']['dosage_for_mname'].'</h3>';
                echo $this->Form->input('med_name',array('type'=>'text','id'=>'med_name','label'=>'Medication Name (Route / Dosage Type)'));
                echo $this->Form->hidden('med_id', array('id' => 'med_id'));
        echo $this->Form->input('meds_taken');
                echo $this->Form->hidden('id', array('id' => 'p_form_id'));
                echo $this->Form->hidden('update_initials',array('value' => $this->Session->read('CoreUser.user_initials')));
                echo $this->Form->hidden('update_time_stamp', array('value' => date("Y-m-d h:i:s")));
    ?>
    </fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<div class="actions">
    <h3><?php echo __('Actions'); ?></h3>
    <ul>

        <li><?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('PsychproConcomitantMed.id')), null, __('Are you sure you want to delete # %s?', $this->Form->value('PsychproConcomitantMed.id'))); ?></li>
        <li><?php echo $this->Html->link(__('List Psychpro Concomitant Meds'), array('action' => 'index')); ?></li>
    </ul>
</div>
<?php echo $this->Html->script('autocomplete_edit'); ?>

jQuery autocomplete

$(document).ready(function(){

    // Defining a placeholder text:
    $('#med_name').defaultText('Search for medications');
    console.log($('#p_form_id').val());
    var form_id = $('#p_form_id').val();

    $('#med_name').autocomplete({
    minLength       : 3,
    source          : 'http://127.0.0.1/my_cakephp/PsychproConcomitantMeds/edit/'+form_id,
    autoFocus       : true,
    select          : function(event,ui){
        //console.log(ui.item['value']);
        $('#med_id').val(ui.item['value']);
        //console.log($('#med_id'));
    }
    });
});

    // A custom jQuery method for placeholder text:

$.fn.defaultText = function(value){

        var element = this.eq(0);
        element.data('defaultText',value);

        element.focus(function(){
        if(element.val() == value){
        element.val('').removeClass('defaultText');
        }
        }).blur(function(){
        if(element.val() == '' || element.val() == value){
        element.addClass('defaultText').val(value);
        }
        });

        return element.blur();
}

Debugging

I know the following is working:

  1. Using the built-in developer tools in chrome I get a response from the jQuery with jQuery array holding the search results in the format {Value: , Label: }.
  2. I know this jQuery code works because I have similar code used for the add method. If you would like to see the code let me know and I will update. The only real difference is that I need to get the id of the record and append it to the end of the URL in the jQuery script.
  3. I'm getting the correct url in the Response. It looks like ../view/21?term=insulin

UPDATE 0:

After some more debugging I finding where the problem is occurring. In the jQuery script for the add method these logs will be printed, but there are not with the edit method.

$('#med_name').autocomplete({
minLength       : 3,
source          : 'http://127.0.0.1/my_cakephp/PsychproConcomitantMeds/edit/'+form_id,
autoFocus       : true,
select          : function(event,ui){
    console.log(ui.item['value']);
    $('#med_id').val(ui.item['value']);
    console.log($('#med_id'));
}
});

So I know that the search function is working, but the select event is not being triggered. The drop down menu is not appearing as well, which I find weird because the jQuery is obviously working since it get the results, they just can't be displayed.

Upvotes: 1

Views: 604

Answers (1)

Tim Sanders
Tim Sanders

Reputation: 851

Not exactly sure what I did, but it's work now. Here is the documentation of the changes made:

autocomplete_edit.js

$(document).ready(function(){
    //console.log('AutocompleteEdit:Function=ready():Beginning');
    // Defining a placeholder text:
    $('#search_key').defaultText('Search here');
    //console.log($('#p_form_id').val());
    var form_id = $('#p_form_id').val();
    var pathname = window.location.pathname;

    $('#search_key').autocomplete({
    minLength       : 3,
    source          : 'http://127.0.0.1'+pathname+'/'+form_id,
    autoFocus       : true,
    select          : function(event,ui){
        //console.log(ui.item['value']);
        $('#search_id').val(ui.item['value']);
        $('#search_key').val(ui.item['label']);
        //console.log($('#med_id'));
    }
    });
});

I changed the ids of the selectors to be more abstract so this autocomplete can be used by other components. I added pathname which gets the webroot and calling controller/method. I'm also get the id of the record so I can store the med_id in a hidden field and keep the name of the medicine in search field.

Updated the edit view

echo '<h3>Current Medication: '.$this->request->data['PidConcomitantMed']['non_proprietary_name'].' Route: '.
 $this->request->data['PidConcomitantMed']['dosage_for_mname'].'</h3>';
echo $this->Form->input('med_name',array('type'=>'text','id'=>'search_key','label'=>'Medication Name (Route / Dosage Type)'));
echo $this->Form->hidden('med_id', array('id' => 'search_id'));
echo $this->Form->input('meds_taken');
echo $this->Form->hidden('id', array('id' => 'p_form_id'));

Upvotes: 1

Related Questions