Apps Script用Sheet生成動態網頁(7): 從sheet內刪除連結列表的項目

我們在 Apps Script用Sheet生成動態網頁(2): 動態生成網頁連結列表 裡,完成了自動從Sheet動態產生連結列表,這篇則是要在裡頭加入刪除功能的按鈕。這樣就完成html的上傳/更新顯示、及刪除功能(本篇)。


1. Apps Script的部份(後端/伺服端)

加入一個刪除用的函數deleteContentFromSheet(),然後我們修改一下權限檢查的函數validateUploadPermission(),讓它可以支援直接返回是否有權限的true/false值。

function deleteContentFromSheet(name) {
validateUploadPermission();
let sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheets()[0]; // 這裡取第一個Sheet
let name_list = sheet.getRange(1, 1 + COLUMN_IDX_OF_NAME, 1 + sheet.getLastRow(), 1).getValues(); // 取回橫列數個儲存格
let row_idx = name_list.findIndex(r => name === r[COLUMN_IDX_OF_NAME]); // 找出吻合的名稱
if (row_idx > 0) sheet.deleteRow(1 + row_idx);
return { deleted: row_idx >= 0 };
}
function validateUploadPermission(notThrow) {
let e = Session.getEffectiveUser();
let a = Session.getActiveUser();
let result = e?.getEmail() === a?.getEmail();
if (notThrow) return result;
if (!result) throw new Error(`您沒有權限上傳檔案,請確認你已經登入Google帳號`);
}

刪除用的函數deleteContentFromSheet()的部份,由於刪除動作是一種危險操作,所以我們會做權限判讀,如果有問題就會讓它拋出錯誤,不繼續執行。

若是有權限可進行,就會在sheet中若有找到html名稱,使用deleteRow()進行刪除。

值得注意的是:deleteRow()在官方文件有說明,是要給定由1開始的Row編號,然而我們的程式的row_idx是從0開始的,所以千萬要記得row_idx加1才不會刪錯橫列。

如果有成功刪除則回傳{deleted:true},這裡要回傳的目的是給前端知道已經刪除;若是沒成功刪除,則可能可以顯示其他的提示訊息給使用者。

2. HTML部份(前端/使用者端)

這裡分為兩個部份,第一個部份是在界面上加入刪除按鈕的部份。

透過使用validateUploadPermission(true)決定目前的使用者是否可以刪除。

<h1>用Sheet內容生成網頁</h1>
<? let BASE_URL = getServerUrl(); ?>
<? let name_list = getNameListFromSheet(); ?>
<? let is_manager = validateUploadPermission(true); ?>

然後在項目中用已決定的is_manager來判斷是否要在後面加入刪除按鈕

<li>
<a href="<?= url ?>">前往<?= name ?></a>
<? if (is_manager) { ?>
<button onclick="onDeleteClicked(event)" name="<?= name ?>">刪除</button>
<? } ?>
</li>

第二個部份是與後端溝通並觸發刪除為onDeleteClicked()函數如下:

function onDeleteClicked(event) {
event.preventDefault();
var name = event.target.name;
var element = event.target;
try {
google.script.run
.withSuccessHandler(function(response, element) {
if (response.deleted && element)
element.parentNode.remove();
})
.withFailureHandler(console.error)
.withUserObject(element)
.deleteContentFromSheet(name);
} catch (error) {
console.error(error);
}
return false;
}

這裡把觸發事件的元素element,透過withUserObject傳到withSuccessHandler中當第二個參數,這樣就可以透過操作element將列表中項目刪除。不要誤會以為用withUserObject是把element傳給後端程式喔!!

而這裡使用parentNode.remove()的原因是element是按鈕,我只刪除按鈕沒有用,需要把包含按鈕所的<li>元素給刪掉,才會讓UI看起來是刪除了。

3. 展示





留言