Sử dụng JQuery Ajax với một số chức năng cơ bản
Giới thiệu chung AJAX ( A synchronous J avaScript A nd X ML) là một kỹ thuật phát triển web có tính tương tác cao thông qua việc kết hợp các công nghệ: XML, HTML, CSS và JavaScript. Trong đó: HTML (hoặc XHTML) với CSStrong việc hiển thị thông tin Mô hình DOM (Document Object Model), được ...
Giới thiệu chung
AJAX (Asynchronous JavaScript And XML) là một kỹ thuật phát triển web có tính tương tác cao thông qua việc kết hợp các công nghệ: XML, HTML, CSS và JavaScript. Trong đó:
- HTML (hoặc XHTML) với CSStrong việc hiển thị thông tin
- Mô hình DOM (Document Object Model), được thực hiện thông qua JavaScript, nhằm hiển thị thông tin động và tương tác với những thông tin được hiển thị.
- Đối tượng XMLHttpRequest để nhận dữ liệu từ server một cách không đồng bộ.
- XML thường là định dạng cho dữ liệu truyền, mặc dầu bất cứ định dạng nào cũng có thể dùng, bao gồm HTML định dạng trước, văn bản thuần (plain text), JSON và ngay cả EBML. Đây là một công nghệ giúp chúng ta tạo ra những Web động mà hoàn toàn không reload lại trang. Đối với công nghệ web hiện nay thì ajax không thể thiếu, nó là một phần làm nên sự sinh động cho website. Ajax được viết bằng ngôn ngữ Javascript nên nó chạy trên client, tức là mỗi máy (user) sẽ chạy độc lập không hoàn toàn ảnh hưởng lẫn nhau. Hiện nay có nhiều thư viện javascript như jQuery hay Angular đều hỗ trợ kỹ thuật này nhằm giúp chúng ta thao tác dễ dàng hơn. Ở bài viết này mình sẽ dùng Ajax với thư viện JQuery.
Làm quen với Ajax đối với 1 số chức năng cơ bản
Mình sẽ tạo app nhỏ để đăng kí và quản lý user và dùng Ajax cho 3 chức năng là tạo mới(create) user, xóa(destroy) user và tìm kiếm(search) user. Đầu tiên, khởi tạo 1 app mới:
rails new ajax_practice
sau đó tạo scaffold user:
rails g scaffold user name:string
Chạy migrate:
rails db:migrate
Để thuận tiện thì mình sẽ gộp toàn bộ các chức năng tạo mới và xóa user trong view index:
Create User
Bình thường khi submit 1 form, params user nhập vào từ client trong 1 request sẽ được routes điều hướng lên server xử lí sau đó sẽ redirect user tới 1 trang khác với thông tin được trả về từ phía server. Đối với Ajax, khi ấn submit, request sẽ thông qua Ajax gửi ngầm lên phía server, dữ liệu trả về sẽ được Ajax tiếp nhận và xử lí theo từng thẻ html riêng biệt trong màn hình hiển thị hiện tại. trong file index.html.erb
<p> We have total <span class="users-size"><%= @users.size %></span> users! </p> <table> . . .
Tạo file ajax.js trong assets/javascripts:
$(document).ready(function() { # ready when html elements and DOM are loaded $('#new_user').on('submit', function(e) { #Bắt event submit của thẻ có id: new_user var name = $('#user_name').val(); # Khai báo và gán giá trị thẻ có id: user_name vào biến name e.preventDefault(); # ngăn chặn hành động mặc định của button submit khi xảy ra sự kiện if (name) { $.ajax({ url: '/users', # gửi request tới server theo đường dẫn /users type: 'post', # phương thức tương ứng là POST dataType: 'json', # data gửi đi dưới dạng JSON data: {user: {name: name}}, # data gửi đi tương ứng với params[:user][:name] }) .done(function(data) { #sau khi Ajax nhận được data từ server trả về và user được save $('tbody').append(data.user_data); #chèn thêm data.user_data vào cuối thẻ <tbody> $('.users-size').text((parseInt($('.users-size').text()) + 1)); # lấy giá trị text của thẻ span có class = users-size, chuyển về dạng int rồi cộng thêm 1, sau đó gán lại vào giá trị text của chính nó }) .fail(function(){ # trường hợp user không save được alert("Can create new user! We got some errors"); }) } else { alert("Name can be blank") } return false; # kết thúc sự kiện }) })
trong users_controller:
class UsersController < ApplicationController . . . def create @user = User.new(user_params) if @user.save render json: { # sau khi user save, trả về client user_data dạng json user_data: render_to_string(@user) # data trả về được render từ html sang chuỗi string, ở đây là partial _user.html.erb }, status: :ok # Rails status code symbol else render error, status: :unauthorized end end private def user_params params.require(:user).permit(:name) end end
Đã xong chức năng tạo mới user, để rõ hơn có thể dùng debugger để thấy sau khi user nhấn submit, hành động mặc định bị hoãn, request từ client được Ajax gửi lên dưới dạng chuỗi JSON { user, { name: name} }. Sau khi xử lí, trên server trả về chuỗi JSON được format thành thẻ <li> rồi dùng javascript chèn vào đầu thẻ <tbody>, đồng thời cũng cập nhật lại giá trị thẻ <p> tương ứng với tổng số user hiện tại.
Delete User
Về chức năng xóa user, cũng gần như tương tự, trong file ajax.js mình thêm sự kiện ấn vào button delete:
$(document).ready(function() { . . . $('.tbody').on('click', '.destroy', function() { var id = $(this).data('id') # Khai báo biến id và gán vào id của user cần delete thông qua thuộc tính data-id của thẻ có class = "destroy" var childTr = $(this).closest('tr') # Khai báo biến childTr và gán vào thẻ <tr> gần nhất của thẻ có class = "destroy" $.ajax({ url: '/users/' + id, type: 'delete' }) .done(function() { childTr.hide(); # ẩn đi thẻ được gán $('.users-size').text((parseInt($('.users-size').text()) - 1)); # cập nhật lại giá trị text của thẻ có class = "user-size" }) return false; }) })
Trong partial _user.html.erb mình set data-id và class ="destroy" cho thẻ <td>
<tr> <td><%= user.name %></td> <td><%= link_to 'Destroy', user, method: :delete, data: {id: user.id}, class: "destroy" %></td> </tr>
Thêm action destroy trong Userscontroller:
class UsersController < ApplicationController . . . def destroy @user = User.find_by id: params[:id] @user.destroy end . .
Sau đó chúng ta có kết quả:
Search User
Bây giờ chúng ta tới chức năng Search, để dễ nhìn thì mình sẽ tạo 1 controller và view search riêng: Đầu tiên, tạo route cho search:
Rails.application.routes.draw do . . resources :searches, only: [:index] end
Ở view search index.html.erb :
<%= form_tag searches_path, method: :get do %> # build form search với request method là get <%= text_field_tag :q, params[:name], # đặt thẻ text input với params[:name] và class = "search-box" class: "search-box", autocomplete: :off %> <span> <%= button_tag "search" %> <%= link_to "Back to index", users_path %> </span> <% end %> <br><br> <table> <thead> <tr> <th>Name</th> <th>Action</th> </tr> </thead> <tbody class="user-table"> <%= render @users %> </tbody> </table>
Trong User model:
class User < ApplicationRecord validates :name, presence: true scope :search, ->q{where "name LIKE ?", "%#{q}%"} end
Ở phía controller:
class SearchesController < ApplicationController def index if request.xhr? # kiểm tra request gửi lên có phải là xhr request của ajax không? @users = User.search(params[:name]) #gọi đến hàm scope :search ở User model render json: { search_result: render_to_string(@users) }, status: :ok else @users = User.all end end end
Còn phần xử lí ajax:
$(document).ready(function() { . . $('.search-box').on('keyup', function() { var key_name = $(this).val(); $.ajax({ url: '/searches', type: 'get', dataType: 'json', data: {name: key_name}, }) .done(function(data) { $('.user-table').html(data.search_result); # Gán giá trị html search_result (được controller trả về) vào thẻ có class = "user-table" // console.log(data.search_result) }) return false; }) })
Và ta được kết quả:
Lời kết
Bài viết này nhằm giới thiệu qua về Jquery Ajax và ứng dụng nó trong 1 số chức năng cơ bản. Bài viết còn tồn tại nhiều hạn chế, rất mong nhận được những đóng góp và phản hồi tích cực. Cảm ơn bạn đã theo dõi bài viết.