Rails – AJAX trong Rails

4.5/5 - (35 votes)

Nếu bạn chưa biết AJAX là gì thì có thể hiểu đơn giản đây là một công nghệ của Javascript, hỗ trợ chúng ta trao đổi dữ liệu giữa server và client (trình duyệt) mà không cần phải gửi các lệnh HTTP thông thường, tức là không cần phải load lại trang web.

Chúng ta sẽ áp dụng AJAX vào nút ‘Add to cart’ để thêm sản phẩm vào giỏ hàng mà không cần phải load lại trang.

Ở phía client, chúng ta sửa lại file index.html.erb trong thư mục app/views/store như sau:

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
 
<h1>Product List</h1>
 
<% @products.each do |product| %>
    <div class="entry">
        <%= image_tag(product.image_url) %>
        <h3><%= product.title %></h3> 
        <%= sanitize(product.description) %>
        <div class="price_line">
            <span class="price"><%= number_to_currency(product.price) %></span>
            <%= button_to 'Add to Cart', 
                          line_items_path(:product_id => product),
                          :remote => true %>
        </div>
    </div>
<% end %>

Ở hàm button_to, chúng ta thêm thuộc tính :remotetrue, và khi bấm vào nút thì trình duyệt sẽ gởi một lời gọi AJAX, thay vì một lời gọi HTTP như bình thường.

Nút này vẫn sẽ gửi tới hàm create trong lớp LineItemsController, do đó ở phía server chúng ta sửa lại như sau:

class LineItemsController < ApplicationController
    .
    .
    .
    # POST /line_items
    # POST /line_items.json
    def create
        @cart = current_cart
        product = Product.find(params[:product_id])
        @line_item = @cart.add_product(product.id)
 
        respond_to do |format| 
            if @line_item.save
                format.html { redirect_to('/', :notice => 'Line item was successfully created') }
                format.js 
                format.json { render :show, status: :created, location: @line_item }
            else
                format.html { render :new }
                format.json { render json: @line_item.errors, status: :unprocessable_entity }
            end
        end
    end
    .
    .
    .
end

Dòng format.js sẽ làm công việc trả lời cho các lời gọi AJAX, mặc định dữ liệu trả về sẽ được gửi trong một file Javascript có tên <tên_phương_thức_routing>.js.erb trong thư mục app/views/<tên_controller>, tức là ở đây sẽ trả về file create.js.erb trong thư mục app/views/line_items.

Do đó chúng ta tạo file create.js.erb có nội dung như sau:

var content = "<%= escape_javascript(render(current_cart)) %>";
document.getElementById("cart").innerHTML = content;

Nếu bạn đã từng làm việc với Javascript thì đoạn code trên cũng không có gì khó hiểu, chỉ khác là chúng ta có thể gọi thêm cả code ERB của Rails trong này. Ở đây chúng ta thay thế nội dung trong thẻ có idcart với biến đã được khai báo là content. Biến này chúng ta truyền vào giá trị lấy từ hàm render current_cart.

Vậy là xong, bây giờ nút ‘Add to cart’ sẽ gửi các lời gọi AJAX thay cho lời gọi HTTP bình thường. Bạn có thể kiểm tra bằng cách để ý icon trên tab của trình duyệt không hiển thị thành vòng tròn xoay, hoặc rõ hơn là lời nhắn thêm sản phẩm thành công của biến :notice'Line item was successfully created' không hiện ra khi chúng ta thêm sản phẩm mới.

Không có AJAX:

bbcapture

Có AJAX:

cc

5 2 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

7 Comments
Inline Feedbacks
View all comments
Kieu Thi Anh
Kieu Thi Anh
7 năm trước

Bai viet cua add rat huu ich a. Em cam on add a.

Nam
Nam
7 năm trước

Giống cuốn Agile web development thế 😀

Nhan
Nhan
6 năm trước

Hi bạn, bài viết của bạn rất hay 🙂
Cho mình hỏi chút mình có làm theo hướng dẫn, có thấy gửi ajax thành công và có nhận được response, tuy nhiên phần js trong views/line_items/create.js.erb lại không thực hiện, tức là giỏ hàng không tự cập nhật lại. Như vậy là bị làm sao bạn nhỉ?

Gia Bao
Gia Bao
6 năm trước

add cho minh hoi chut sau khi xoa gio hang.. thi bi loi .. bi gia tri nil.. lam sao khac phuc duoc v