Autocomplete textbox in CodeIgniter 4 with jQuery UI

Autocomplete textbox in CodeIgniter 4 with jQuery UI


jQuery UI autocomplete display suggestions list based on the input in the textbox.

You can display suggestions with and without AJAX.

In this tutorial, I show how you can add jQuery UI autocomplete and load MySQL database data using jQuery AJAX in the CodeIgniter 4 project.


 1. Database configuration

  • Open .env file which is available at the project root.

NOTE – If dot (.) not added at the start then rename the file to .env.

  • Remove # from start of database.default.hostname, database.default.database, database.default.username, database.default.password, and database.default.DBDriver.
  • Update the configuration and save it.
database.default.hostname = 127.0.0.1
database.default.database = testdb
database.default.username = root
database.default.password = 
database.default.DBDriver = MySQLi

2. Enable CSRF

  • Again open .env file.
  • Remove # from the start of the app.CSRFProtection, app.CSRFTokenNameapp.CSRFCookieNameapp.CSRFExpire, and app.CSRFRegenerate.
  • I update the app.CSRFTokenName value with 'csrf_hash_name'. With this name read CSRF hash. You can update it with any other value.
  • If you don’t want to regenerate CSRF hash after each AJAX request then set app.CSRFRegenerate = false.
app.CSRFProtection = true
app.CSRFTokenName = 'csrf_hash_name'
app.CSRFCookieName = 'csrf_cookie_name'
app.CSRFExpire = 7200
app.CSRFRegenerate = true
# app.CSRFExcludeURIs = []
  • Open app/Config/Filters.php file.
  • Uncomment in 'csrf' in 'before' if commented.
// Always applied before every request
public $globals = [
    'before' => [
       //'honeypot'
       'csrf',
    ],
    'after' => [
       'toolbar',
       //'honeypot'
    ],
];

3. Create Table

  • Create a new table users using migration.
php spark migrate:create create_users_table
  • Now, navigate to app/Database/Migrations/ folder from the project root.
  • Find a PHP file that ends with create_users_table and open it.
  • Define the table structure in the up() method.
  • Using the down() method delete users table which calls when undoing migration.
<?php namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateUsersTable extends Migration
{
    public function up() {
       $this->forge->addField([
          'id' => [
              'type' => 'INT',
              'constraint' => 5,
              'unsigned' => true,
              'auto_increment' => true,
          ],
          'name' => [
              'type' => 'VARCHAR',
              'constraint' => '100',
          ],
          'email' => [
              'type' => 'VARCHAR',
              'constraint' => '100',
          ],
          'city' => [
              'type' => 'VARCHAR',
              'constraint' => '100',
          ],
       ]);
       $this->forge->addKey('id', true);
       $this->forge->createTable('users');
    }

    //--------------------------------------------------------------------

    public function down() {
       $this->forge->dropTable('users');
    }
}
  • Run the migration –
php spark migrate

4. Download jQuery UI

  • Download the jQuery UI plugin from here.
  • Extract it in the public/ folder at the root.
  • You can also use CDN –
<!-- Script -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- jQuery UI -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

5. Model

  • Create Users.php file in app/Models/ folder.
  • Open the file.
  • Specify table name "users" in $table variable, primary key "id" in $primaryKey, Return type "array" in $returnType.
  • In $allowedFields Array specify field names – ['name','email','city'] that can be set during insert and update.

Completed Code

<?php 
namespace App\Models; 
use CodeIgniter\Model;

class Users extends Model { 
   protected $table = 'users'; 
   protected $primaryKey = 'id'; 
   protected $returnType = 'array'; 
   protected $allowedFields = ['name', 'email','city']; 
   protected $useTimestamps = false; 
   protected $validationRules = []; 
   protected $validationMessages = []; 
   protected $skipValidation = false; 
}

6. Route

  • Open app/Config/Routes.php file.
  • Define 2 routes –
    • /
    • users/getUsers – It is used to load autocomplete data.

Completed Code

$routes->get('/', 'UsersController::index');
$routes->post('users/getUsers', 'UsersController::getUsers');

7. Controller

  • Create UsersController.php file in app/Controllers/ folder.
  • Open the file.
  • Import Users Model.
  • Create 2 methods –
    • index() – Load index view.
    • getUsers() – This method is use to handle jQuery UI autocomplete AJAX requests.

Read POST values and assign to $postData variable. Create $response Array to store return response. Assign new CSRF token to $response['token'].

If search is POST then assign $postData['search'] to $search and fetch records from users table where search exists in the name field.

Loop on the fetched records and initialize $data Array with value and label keys. Assign $user['id'] to 'value' key and $user['name'] to 'label' key.

Assign $data Array to $response['data'].

Return $response Array in JSON format.

Completed Code

<?php namespace App\Controllers;

use App\Models\Users;

class UsersController extends BaseController{

   public function index(){
      return view('index');
   }

   public function getUsers(){

      $request = service('request');
      $postData = $request->getPost();

      $response = array();

      // Read new token and assign in $response['token']
      $response['token'] = csrf_hash();
      $data = array();

      if(isset($postData['search'])){

         $search = $postData['search'];

         // Fetch record
         $users = new Users();
         $userlist = $users->select('id,name')
                ->like('name',$search)
                ->orderBy('name')
                ->findAll(5);
         foreach($userlist as $user){
             $data[] = array(
                "value" => $user['id'],
                "label" => $user['name'],
             );
         }
      }

      $response['data'] = $data;

      return $this->response->setJSON($response);

   }
}

8. View

Create index.php file in app/Views/.

Create a hidden element to store CSRF token name specified in .env file in the name attribute and store CSRF hash in the value attribute.

<input type="hidden" class="txt_csrfname" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" />

Create 2 text elements. The first text element is used to initialize autocomplete and the second element is used to store selected suggestion item value.

Script –

Initialize autocomplete on #autocompleteuser.

With 'source' option load data.

Read CSRF Token name and hash from the hidden field and assign it to the csrfName and csrfHash.

Send AJAX request to "<?=site_url('users/getUsers')?>"type: "post"dataType: 'json'.

Pass typed value and CSRF token as data.

On successful callback update CSRF token value $('.txt_csrfname').val(data.token).

Pass data.data to response() function.

With the 'select' event get the selected suggestion label and value.

Pass ui.item.label in #autocompleteuser selector and ui.item.value in #userid selector.

Completed Code

<!doctype html>
<html>
<head>
   <title>Autocomplete textbox in CodeIgniter 4 with jQuery UI</title>

   <!-- jQuery UI CSS -->
   <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
   <!-- <link rel="stylesheet" type="text/css" href="/jquery-ui/jquery-ui.min.css"> -->

   <!-- jQuery -->
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

   <!-- jQuery UI JS -->
   <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
   <!-- <script type="text/javascript" src="/jquery-ui/jquery-ui.min.js"></script> -->
</head>
<body>

   <!-- CSRF token --> 
   <input type="hidden" class="txt_csrfname" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" />
   
   <!-- Autocomplete -->
   Search User : <input type="text" id="autocompleteuser">

   <br><br>
   Selected user id : <input type="text" id="userid" value='0' >

   <!-- Script -->
   <script type='text/javascript'>
   $(document).ready(function(){
     // Initialize
     $( "#autocompleteuser" ).autocomplete({

        source: function( request, response ) {

           // CSRF Hash
           var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
           var csrfHash = $('.txt_csrfname').val(); // CSRF hash

           // Fetch data
           $.ajax({
              url: "<?=site_url('users/getUsers')?>",
              type: 'post',
              dataType: "json",
              data: {
                 search: request.term,
                 [csrfName]: csrfHash // CSRF Token
              },
              success: function( data ) {
                 // Update CSRF Token
                 $('.txt_csrfname').val(data.token);

                 response( data.data );
              }
           });
        },
        select: function (event, ui) {
           // Set selection
           $('#autocompleteuser').val(ui.item.label); // display the selected text
           $('#userid').val(ui.item.value); // save selected id to input
           return false;
        },
        focus: function(event, ui){
          $( "#autocompleteuser" ).val( ui.item.label );
          $( "#userid" ).val( ui.item.value );
          return false;
        },
      }); 
   }); 
   </script> 
</body> 
</html>

9. Run & Demo

  • Navigate to the project using Command Prompt if you are on Windows or terminal if you are on Mac or Linux, and
  • Execute “php spark serve” command.
php spark serve
  • Run http://localhost:8080 in the web browser.

View Demo


10. Conclusion

Returned autocomplete data from the controller must have ‘value’ and ‘label’ keys. Adjust LIMIT according to your requirement.

NOTE – If the CSRF token is not enabled in your project then remove the CSRF token code from the controller and view.

If you found this tutorial helpful then don't forget to share.



Comments