07/09/2018, 10:42

Tạo Chức Năng Autocomplete trong AngularJS với PHP và MySQL

Trong bài viết này chúng ta sẽ tìm hiểu cách tạo một form để search tên người dùng hỗ trợ tính năng autocomplete sử dụng AngularJs kết hợp với phía backend được xây dựng sử dụng PHP và MySQL. Ứng dụng bao gồm việc xây dựng một app phía backend để trả về dữ liệu khi nhận được request gửi từ client ...

Trong bài viết này chúng ta sẽ tìm hiểu cách tạo một form để search tên người dùng hỗ trợ tính năng autocomplete sử dụng AngularJs kết hợp với phía backend được xây dựng sử dụng PHP và MySQL.

Ứng dụng bao gồm việc xây dựng một app phía backend để trả về dữ liệu khi nhận được request gửi từ client (thông qua AJAX) và sau đó ở phía client sẽ triển khai việc gửi request tới server để tìm kiếm kết quả sử dụng AngularJS.

Tải Source Code: Bạn có thể tải source code của dự án tại địa chỉ sau.

Bước 1: Tạo Database, Bảng và Thêm Dữ Liệu

Tạo Database

Đầu tiên chúng ta cần tạo database cho ứng dụng. Sử dụng MySQL client và login vào MySQL server:

mysql -u rooot -p

Nhập passwword cho user root hoặc bất cứ user nào bạn sử dụng để truy cập vào MySQL server ở câu lệnh trên.

Lưu ý: Bạn có thể sử dụng PhpMyAdmin để thực hiện các bước trong phần này nếu bạn thích làm việc với giao diện UI hơn cửa sổ dòng lệnh.

Sau đó tạo một dataase với tên angular_autocomplete:

create database angular_autocomplete;

Thêm Bảng users

Tiếp theo chúng ta sẽ tạo bảng user cho database vừa mới tạo ra.

Trước tiên chúng ta cần chọn database mới tạo là database mà chúng ta sẽ làm việc với nó:

use angular_autocomplete

Chạy câu lệnh sau để tạo bảng users:

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(80) NOT NULL,
  `name` varchar(80) NOT NULL,
  `email` varchar(80) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1

Thêm Dữ Liệu Vào Bảng

Chúng ta sẽ kết thúc bước này bằng việc thêm dữ liệu vào bảng users vừa mới được tạo ở trên:

INSERT INTO `users` (`id`, `username`, `name`, `email`) VALUES
(1, 'johndoe', 'John Doe', 'johndoe@example.net');

Tới đây chúng ta đã hoàn thành bước đầu tiên.

Bước 2: Tạo App Backend Với PHP

Ở bước này chúng ta sẽ tạo một web app bằng PHP để thực hiện việc truy vấn database lấy kết quả trả về cho phía client.

Trong thư mục root (hay gốc) của web server và tạo một fil config_db với nội dung như sau:

<?php

$host = "localhost"; /* DB host name */
$user = "root"; /* DB user */
$password = ""; /* DB password */
$dbname = "angular_autocomplete"; /* DB name */

$con = mysqli_connect($host, $user, $password,$dbname);

// Check connection
if (!$con) {
    die("Connection failed: " . mysqli_connect_error());
}

Ở trên chúng ta thực hiện việc kết nối tới MySQL thông qua hàm mysqli_connect() của PHP. Bạn cần thay đổi các giá trị như $user và password phù hợp với người dùng MySQL có trên máy của bạn.

Tiếp theo tạo một file search.php nằm trong cùng thư mục với file config trên với nội dung như sau:

<?php
require_once 'config_db.php';

$name = isset($_POST['name']) ? $_POST['name'] : ';

$data = [];

// Search users by name limit 10 records
$sql = "SELECT * FROM users WHERE name LIKE '%" . $name . "%' LIMIT 10";
$result = mysqli_query($con, $sql);

while($row = mysqli_fetch_array($result)) {
    $data[] = ["name" => $row['name']];
}

echo json_encode($data);

Ở trên đầu tiên chúng ta load tập tin config_db.php để kết nối với database mới tạo trước đó. Sau đó tạo một câu lệnh thực hiện truy vấn dữ liệu trong bảng users với giá trị của trường name giống với giá trị của biến name trong POST request gửi tới PHP:

$sql = "SELECT * FROM users WHERE name LIKE '%" . $name . "%' LIMIT 10";
$result = mysqli_query($con, $sql);

Sau đó kết quả trả về lần lượt được tách ra sử dụng hàm mysqli_fetch_array() và đưa vào mảng $data trước khi trả về response dạng JSON.

Bước 3: Tạo App Frontend với AngluarJS và Twitter Bootstrap

Cấu Trúc File HTML Với Twitter Bootstrap

Để bắt triển khai tính năng search autocomplete sử dụng AngularJS ở phía frontend chúng ta sẽ tạo một trang HTML sử dụng Twitter Bootstrap framework và nhúng thư viện Angular. Trong thư mục dự án bạn tạo một tập tin index.php (hoặc index.html) với nội dung như sau:

<!DOCTYPE html>
<html>
<head>
    <title>Autocomplete AngularJS</title>

     
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

     
    <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</head>
<body ng-app="myapp">
</body>
</html>

Ở đoạn code HTML trên, chúng ta nhúng các file JavaScript và CSS của thư viện Twitter Bootstrap framework cùng với các thư viện dependency như jQuery và Tether mà Twitter Bootstrap cần tới. Ngoài ra thì chúng ta cũng nhúng file JavaSCript chứa thư viện AngularJS vào trang. Bạn cũng lưu bên trong thẻ mở <body> chúng ta có một directive ng-app để tạo một module myapp.

Bên trong thẻ <body> bạn thêm vào đoạn code HTML sau:

<div class="container">
    <h4>Tìm Kiếm Người Dùng</h4>
    <div class="row">
        <div class="col-4">
            <form>
                <div class="form-group">
                    <div class="dropdown" ng-controller="searchCtrl">
                        <label for="name">Nhập tên:</label>
                        <input type="text" ng-keyup="searchUsers()" ng-model="name" class="form-control" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                        <ul id="list-users" class="dropdown-menu" aria-labelledby="dropdownMenu1">
                            <a class="dropdown-item" ng-click="setValue($index)" ng-repeat="result in searchResult" >{{result.name}}</a>
                        </ul>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

Ở trên chúng ta sử dụng các class được quy định bởi Twitter Bootstrap như container, row, col-4, dropdown... Ngoài ra thì bạn cần chú ý tới các directive như là:

  • ng-controller="searchCtrl": Directive này dùng để bắt đầu một controller với tên searchCtrl. Chúng ta sẽ định nghĩa controller này trong file JavaScript ở phần tiếp theo dưới đây.
  • ng-keyup="searchUser()": Directive này được đặt trên trường nhập dữ liệu <input> với tác dụng là sẽ trigger hàm searchUser() khi người dùng nhập dữ liệu vào trường. Hàm này cũng sẽ được chúng ta khai báo trong file JavaScript ở phần tiếp theo dưới đây.
  • Tạm thời tôi sẽ bỏ qua việc giải thích ý nghĩa hai directive ng-click="setValue($index)" và ng-repeat="result in searchResult" trong thẻ <a> và sẽ quay lại sau.

Triển Khai Autocomplete với AngularJS

Sau khi đã xây dựng app backend và tạo cấu trúc HTML thì tới bước này chúng ta đã sẵn sàng để triển khai tính năng autocomplete sử dụng AngularJS. Bạn tạo một file script.js trong cùng thư mục với thư mục chứa file index.php ở trên với nội dung sau:

var myapp = angular.module('myapp', []);

myapp.controller('searchCtrl', ['$scope', '$http', function ($scope, $http) {

    // Fetch data
    $scope.searchUsers = function() {
        $http({
            method: 'POST',
            url: 'search.php',
            data: {
                name: $scope.name
            }
        }).then(function successCallback(response) {
            $scope.searchResult = response.data;
        });
    }

    // Set value to search box
    $scope.setValue = function(index) {
        $scope.name = $scope.searchResult[index].name;
        $scope.searchResult = {};
    }

}]);

Ở trên chúng ta đã sử dụng biến $scope của AngularJS và $http service khi khai báo controller searchCtrl. Trong controller này chúng ta khai báo hàm searchUsers() sử dụng trong view (hay template) mà chúng ta đã tạo ở bước trước. Kkhi được gọi hàm này thực hiện việc việc gửi một AJAX request tới file search.php trên server dưới phương thức POST với dữ liệu là thuộc tính name của $scope. Giá trị của thuộc tính này được lấy từ giá trị nhập vào trường <input>. Điều này là bởi vì trên thẻ <input> này có một directive là ng-model dùng để bind giá trị trong template với controller:

<input type="text" ng-keyup="searchUsers()" ng-model="name" class="form-control" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">

Sau khi trình duyệt nhận được kết quả trả về từ server cho AJAX request gửi đi thì hàm successCallback sẽ gán giá trị của response.data vào thuộc tính searchResult của $scope. Nhớ lại rằng server trả về response data dạng JSON là một mảng với mỗi phần tử chứa trường name và giá trị tương ứng:

while($row = mysqli_fetch_array($result)) {
    $data[] = ["name" => $row['name']];
}

echo json_encode($data);

Lúc này directvive ng-repeat được sử dụng trong thẻ <a> của template sẽ được dùng đển hiển thị giá trị của trường name của từng phần tử trong mảng trả về:

<ul id="list-users" class="dropdown-menu" aria-labelledby="dropdownMenu1">
    <a class="dropdown-item" ng-click="setValue($index)" ng-repeat="result in searchResult" >{{result.name}}</a>
</ul>

Ngoài ra thì khi người dùng click vào phần tử <a> hiển thị trong kết quả trả về thì hàm setValue($index) sẽ được gọi (thuộc tính đặc biệt $index được sử dụng cùng với directive ng-repeat để lấy giá trị index của phần tử trong mảng lặp). Hàm setValue() được khai báo trong file JavaScript như sau:

$scope.setValue = function(index) {
    $scope.name = $scope.searchResult[index].name;
    $scope.searchResult = {};
}

Như vậy ở trong hàm trên chúng ta thực hiện hai việc:

  • Gán giá trị cho thuộc tính name của $scope. Bạn lưu ý giá trị của thuộc tính này được phản ánh thông qua directive ng-model có trong thẻ <input> trong template.
  • Thiết lập lại giá trị của thuộc tính searchResult về một object rỗng.

Bây giờ bạn có thể kiểm tra lại bằng cách mở trình duyệt và truy cập vào địa chỉ URL trỏ tới file index.php trên server. Sau đó trong trường <input> bạn nhập vào ký tự j. Nếu làm đúng theo hướng dẫn bạn sẽ thấy một dropdown hiển thị kết quả trả về với tên là John Doe.

Chúc bạn thành công!

0