承接上篇所提,我們利用jQuery的AJAX功能,雖然沒有ujs的方便性,但是對未來擴增及撰寫彈性是有優勢的。
以下介紹一下,怎麼樣用jQuery完成一些AJAX功能
jQuery自帶ajax方法
但是在rails底下要注意CSRF的問題
簡單來說,就是會在網頁裡面放token,在執行網頁動作時隨附token,讓伺服器可以驗證,確保安全。
然後rails 5.1已經自帶rails-ujs.js
記得在 application.js 裡寫入//= require rails-ujs
這樣所有ajax請求都會自動被加入csrf token
這邊就開始寫ajax囉
$.ajax 方法要帶入一個 object
這邊提醒一下javascript的object寫法
物件(objects):
1. 以 {} 包含
2. 有 Key & Value , 如: var obj = { one:1, two:2, three:3, four:4, five:5 };
最基本的jquery ajax寫法包含
url:發送非同步請求的對象,也就是索求資料的 server 的網址
method:發送請求的類型,如 GET、POST、DELETE、PATCH 等
data:要附帶在請求裡發送給 server 的資料
dataType:要求 server 回傳的資料格式
success:成功後要執行的 function,function 會帶入 server 回傳的資料
以Destroy例如
$("#todolist").on("click", ".delete-todo", function(event) {
var id = event.target.parentNode.parentNode.id;
$.ajax({
url: "todos/" + id,
method: "DELETE",
dataType: "json",
success: function(data) {
$("#" + data["id"]).remove();
}
});
});
這邊用on的函式是為了解決動態的元件,如果在#todolist底下做click動作而且又是按.delete-todo這個元件,就會啟動function
上面的範例中.delete-todo是會臨時增減的,如果用傳統的click()方法寫,在動態新增.delete-todo之後,會抓不到這個新的.delete-todo
然後裡面的這個var id是用來找到@todo的id
來對應route裡面的路徑(範例中是/todos/:id(.:format))
設定好格式json,這樣子等一下可以回傳id,來執行刪除的jQuery
(其實可以直接抓上面的var id,不過習慣利用回傳的data做事情,對create、update等動作會有幫助)
所以就要把controller這邊也寫完,回傳json
def destroy
@todo = Todo.find(params[:id])
@todo.destroy
render :json => { :id => @todo.id } #就是這行
end
這樣就完成Destroy囉
再來看一下更複雜的Create
直接上程式碼
$("#create-todo").on("click", function(event) {
event.preventDefault();
$.ajax({
url: "todos/",
method: "POST",
dataType: "json",
data: {
todo: {
title: $("#new-todo").val()
}
},
success: function(data) { }
});
});
首先,event.preventDefault()是用來阻止瀏覽器做預設的動作
在form裡的button預設的動作就是送出表單
他會自己執行post,但我們不要
因為我們要用ajax做post,不是瀏覽器做
然後再來的話設定method post, type json
並且找到對應的url,這些應該都不是問題
問題是data,在Rails 4之後加入了strong params規定
也就是寫入資料時必須先設定好傳什麼變數進來,沒有設定的就不給傳
來看一下這個範例的controller的strong params是怎麼寫的
def todo_params
params.require(:todo).permit(:title)
end
所以你要手刻傳給伺服器的資料就必須符合規定
簡單來說就是要傳一個”todo”的資料、而且裡面有title
伺服器才給放行
所以我們就把todo及title用json的寫法包起來
就可以順利的讓伺服器寫入了
然後如果你需要在同一個頁面看到你新增的結果
也是跟destroy一樣,在controller action裡寫回傳json
利用這個回傳的json,在success: function(data){}裡面做你想要做的事情
其實寫到後面發現
要作ajax這個並不難,只是如果你需要同步更新網頁
(譬如說把你新增、修改的內容要即時更新)
就會需要寫很多jQuery、javascript、HTML DOM的東西
舉例來說
在AC的課程裡,教學任務寫了如何在按下編輯之後
使todo的文字變成編輯框、編輯完送出之後馬上改變
使這些流程完全靠ajax,在寫jQuery時就會變得很複雜
可以包成像這樣的邏輯
設定 edit 按鈕事件驅動
抽換表單
設定 update 按鈕事件驅動
恢復文字欄位
結束 update 按鈕事件驅動
結束 edit 按鈕事件驅動
就會在edit按鈕的.on事件裡面放.ajax
然後success裡面 再放一個.on,再放.ajax
最後success裡面回復文字欄位這樣…
最後補充一些,關於strong params的分享
因為未來可能會傳一些比較複雜的變數
或是一個變數擁有多個值這樣
這篇有點偷懶,就先降~