CakePHP 3 Tutorial 18: Autocomplete

Submitted by naidim on Tue, 10/25/2016 - 12:30

In the previous two tutorials we discussed adding associated records. But what if you want to select a record from an associated table where there are thousands of records? Autocomplete can help with this issue, but it requires a combination of parts to work.

1. Get List of Selections

In the users controller (src/Controller/UsersController.php) create a function that returns a list of records based on the input into the form field.

public function getAll()
{
    if ($this->requrest->is('ajax')) {
        $this->autoRender = false;
        $name = $this->request->query['term'];
        $results = $this->Users->find('all', [
            'conditions' => [ 'OR' => [
                'first_name LIKE' => $name . '%',
                'last_name LIKE' => $name . '%',
            ]]
        ]);
        $resultsArr = [];
        foreach ($results as $result) {
             $resultsArr[] =['label' => $result['full_name'], 'value' => $result['id']];
        }
        echo json_encode($resultsArr);
    }
}

2. Include jQuery

To utilize the jQuery autocomplete() functionality, you need to load the jQuery library. The easiest place to add this is in your default layout (/src/Template/Layout/default.ctp).

<head>
   ...
   echo $this->Html->script('//code.jquery.com/jquery-1.10.2.js');
   echo $this->Html->script('//code.jquery.com/ui/1.11.4/jquery-ui.js');
   echo $this->Html->css('//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css');
   ...

3. Add/Edit Form Code

Then in your phone number "add" and "edit" views (/src/Template/PhoneNumbers/add.ctp), add the scripting to call jQuery's autocomplete() method which in turn calls the user getAll() function.

<?php use Cake\Routing\Router; ?>
...
    echo $this->Form->input('user_id', ['type' => 'text']);
...
<script>
    jQuery('#user-id').autocomplete({
        source:'<?php echo Router::url(array('controller' => 'Users', 'action' => 'getAll')); ?>',
        minLength: 3
    });
</script>

Now when you start typing in a name, first or last, into the user_id field, the autocomplete list should appear allowing you to choose the user from the list. You can remove the request for the list of users from your phone numbers controller at this time since it is no longer used.

However, once you choose the user's name from the autocomplete list, the user's id will appear in the field. This will work, but may confuse your site's users. We'll correct this in the next tutorial.

Next: Display One Thing, Save Another

Comments

Submitted by DLynn on Wed, 02/22/2017 - 08:01

Permalink

I have a containers/add template with this autocomplete set on the Address field. The Addresses controller has the getAll method as described. I get "unable to emit headers" error that says Addresses has already started the header. This seems to be coming from the echo json_encode($resultsArr); statement.

What step am I overlooking?

Submitted by Ana on Thu, 06/01/2017 - 23:47

Permalink

Thanks, it's just what I was looking for!!!

Add new comment