คู่มือนี้อธิบายวิธียืนยันตัวแปรอินพุต
เมื่อกำหนดตัวแปรอินพุต แนวทางปฏิบัติแนะนำคือให้ยืนยันว่าผู้ใช้ป้อนค่าที่เหมาะสม ตัวอย่างเช่น หากคุณขอให้ผู้ใช้ป้อนตัวเลข
การยืนยันว่าผู้ใช้ป้อน 1 แทน a จะยืนยันว่าขั้นตอนของคุณ
ทำงานโดยไม่มีข้อผิดพลาด
การยืนยันตัวแปรอินพุตทำได้ 2 วิธีดังนี้
- การยืนยันฝั่งไคลเอ็นต์: การยืนยันฝั่งไคลเอ็นต์ช่วยให้คุณยืนยันอินพุตของผู้ใช้ได้โดยตรงใน อุปกรณ์ของผู้ใช้ ผู้ใช้จะได้รับความคิดเห็นทันทีและสามารถแก้ไขข้อผิดพลาดในอินพุตได้ขณะกำหนดค่าขั้นตอน
- การยืนยันฝั่งเซิร์ฟเวอร์: การยืนยันฝั่งเซิร์ฟเวอร์ช่วยให้คุณเรียกใช้ตรรกะในเซิร์ฟเวอร์ระหว่างการยืนยัน ซึ่งมีประโยชน์เมื่อคุณต้องการค้นหาข้อมูลที่ไคลเอ็นต์ไม่มี เช่น ข้อมูลในระบบหรือฐานข้อมูลอื่นๆ
การยืนยันฝั่งไคลเอ็นต์
การยืนยันฝั่งไคลเอ็นต์ทำได้ 2 วิธีดังนี้
- สำหรับการยืนยันพื้นฐาน เช่น การยืนยันว่าวิดเจ็ตมีอักขระไม่เกินจำนวนที่กำหนดหรือมีสัญลักษณ์
@ให้เรียกใช้คลาสValidationของบริการการ์ดของส่วนเสริม Google Workspace - สำหรับการยืนยันที่รัดกุม เช่น การเปรียบเทียบค่าของวิดเจ็ตกับค่าของวิดเจ็ตอื่นๆ
คุณสามารถเพิ่มการยืนยัน Common Expression Language (CEL)
ลงในวิดเจ็ตการ์ดที่รองรับต่อไปนี้โดยใช้
CardService
เรียกใช้คลาส Validation
ตัวอย่างต่อไปนี้จะยืนยันว่าวิดเจ็ต TextInput มีอักขระไม่เกิน 10 ตัว
Apps Script
const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
CardService.InputType.TEXT);
หากต้องการตัวเลือกการยืนยันเพิ่มเติม ให้ใช้การยืนยัน CEL
การยืนยัน CEL
การตรวจสอบ Common Expression Language (CEL) ช่วยให้ตรวจสอบอินพุตได้ทันทีโดยไม่มีเวลาในการตอบสนองของการตรวจสอบฝั่งเซิร์ฟเวอร์ โดยการลดภาระการตรวจสอบค่าอินพุตที่ไม่ขึ้นอยู่กับการค้นหาข้อมูลจากบริการอื่นๆ ไปยังฝั่งไคลเอ็นต์
นอกจากนี้ คุณยังใช้ CEL เพื่อสร้างลักษณะการทำงานของการ์ดได้ด้วย เช่น การแสดงหรือซ่อนวิดเจ็ตโดยขึ้นอยู่กับผลลัพธ์ของการยืนยัน ลักษณะการทำงานประเภทนี้มีประโยชน์สำหรับการแสดงหรือซ่อนข้อความแสดงข้อผิดพลาดที่จะช่วยให้ผู้ใช้แก้ไขอินพุตได้
การสร้างการยืนยัน CEL ที่สมบูรณ์ประกอบด้วยคอมโพเนนต์ต่อไปนี้
ExpressionDataในการ์ด: มีตรรกะการยืนยันและตรรกะการทริกเกอร์วิดเจ็ตที่ระบุไว้เมื่อตรงตามเงื่อนไขที่กำหนดไว้ข้อใดข้อหนึ่งId: ตัวระบุที่ไม่ซ้ำกันสำหรับExpressionDataภายในการ์ดปัจจุบันExpression: สตริง CEL ที่กำหนดตรรกะการยืนยัน (เช่น"value1 == value2")Conditions: รายการเงื่อนไขที่มีผลลัพธ์การยืนยันที่กำหนดไว้ล่วงหน้า (SUCCESS หรือ FAILURE) ให้เลือก เงื่อนไขจะเชื่อมโยงกับEventActionฝั่งวิดเจ็ตผ่านTriggersที่มีactionRuleIdร่วมกันEventActionระดับการ์ด: เปิดใช้งานการยืนยัน CEL ในการ์ดและเชื่อมโยงฟิลด์ExpressionDataกับวิดเจ็ตผลลัพธ์ผ่านทริกเกอร์หลังเหตุการณ์actionRuleId: รหัสที่ไม่ซ้ำกันสำหรับEventActionนี้ExpressionDataAction: ตั้งค่าเป็นSTART_EXPRESSION_EVALUATIONเพื่อระบุว่าการดำเนินการนี้เริ่มการประเมิน CELTrigger: เชื่อมต่อConditionsกับEventActionsฝั่งวิดเจ็ตโดยอิงตามactionRuleId
EventActionระดับวิดเจ็ต: ควบคุมลักษณะการทำงานของวิดเจ็ตผลลัพธ์เมื่อตรงตามเงื่อนไขสำเร็จหรือล้มเหลว ตัวอย่างเช่น วิดเจ็ตผลลัพธ์อาจเป็นTextParagraphที่มีข้อความแสดงข้อผิดพลาดซึ่งจะปรากฏขึ้นเมื่อการยืนยันล้มเหลวเท่านั้นactionRuleId: ตรงกับactionRuleIdในTriggerฝั่งการ์ดCommonWidgetAction: กำหนดการดำเนินการที่ไม่เกี่ยวข้องกับการประเมิน เช่น การอัปเดตการมองเห็นวิดเจ็ตUpdateVisibilityAction: การดำเนินการที่อัปเดตสถานะการมองเห็นของวิดเจ็ต (VISIBLE หรือ HIDDEN)
ตัวอย่างต่อไปนี้แสดงวิธีใช้การยืนยัน CEL เพื่อตรวจสอบว่าอินพุตข้อความ 2 รายการเท่ากันหรือไม่ ระบบจะแสดงข้อความแสดงข้อผิดพลาดหากอินพุตไม่เท่ากัน
-
รูปที่ 1: เมื่อตรงตาม failCondition(อินพุตไม่เท่ากัน) ระบบจะตั้งค่าวิดเจ็ตข้อความแสดงข้อผิดพลาด เป็นVISIBLEและวิดเจ็ตจะปรากฏขึ้น -
รูปที่ 2: เมื่อตรงตาม successCondition(อินพุตเท่ากัน) ระบบจะตั้งค่าวิดเจ็ตข้อความแสดงข้อผิดพลาดเป็นHIDDENและวิดเจ็ตจะไม่ปรากฏขึ้น
ตัวอย่างโค้ดของแอปพลิเคชันและไฟล์ Manifest JSON มีดังนี้
Apps Script
function onConfig() {
// Create a Card
let cardBuilder = CardService.newCardBuilder();
const textInput_1 = CardService.newTextInput()
.setTitle("Input field 1")
.setFieldName("value1"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
const textInput_2 = CardService.newTextInput()
.setTitle("Input field 2")
.setFieldName("value2"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
let sections = CardService.newCardSection()
.setHeader("Enter same values for the two input fields")
.addWidget(textInput_1)
.addWidget(textInput_2);
// CEL Validation
// Define Conditions
const condition_success = CardService.newCondition()
.setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
.setExpressionDataCondition(
CardService.newExpressionDataCondition()
.setConditionType(
CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_SUCCESS));
const condition_fail = CardService.newCondition()
.setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
.setExpressionDataCondition(
CardService.newExpressionDataCondition()
.setConditionType(
CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_FAILURE));
// Define Card-side EventAction
const expressionDataAction = CardService.newExpressionDataAction()
.setActionType(
CardService.ExpressionDataActionType.START_EXPRESSION_EVALUATION);
// Define Triggers for each Condition respectively
const trigger_success = CardService.newTrigger()
.setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID");
const trigger_failure = CardService.newTrigger()
.setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID");
const eventAction = CardService.newEventAction()
.setActionRuleId("CEL_TEXTINPUT_EVALUATION_RULE_ID")
.setExpressionDataAction(expressionDataAction)
.addPostEventTrigger(trigger_success)
.addPostEventTrigger(trigger_failure);
// Define ExpressionData for the current Card
const expressionData = CardService.newExpressionData()
.setId("expData_id")
.setExpression("value1 == value2") // CEL expression
.addCondition(condition_success)
.addCondition(condition_fail)
.addEventAction(eventAction);
card = card.addExpressionData(expressionData);
// Create Widget-side EventActions and a widget to display error message
const widgetEventActionFail = CardService.newEventAction()
.setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
.setCommonWidgetAction(
CardService.newCommonWidgetAction()
.setUpdateVisibilityAction(
CardService.newUpdateVisibilityAction()
.setVisibility(
CardService.Visibility.VISIBLE)));
const widgetEventActionSuccess = CardService.newEventAction()
.setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
.setCommonWidgetAction(
CardService.newCommonWidgetAction()
.setUpdateVisibilityAction(
CardService.newUpdateVisibilityAction()
.setVisibility(
CardService.Visibility.HIDDEN)));
const errorWidget = CardService.newTextParagraph()
.setText("<font color=\"#FF0000\"><b>Error:</b> Please enter the same values for both input fields.</font>")
.setVisibility(CardService.Visibility.HIDDEN) // Initially hidden
.addEventAction(widgetEventActionFail)
.addEventAction(widgetEventActionSuccess);
sections = sections.addWidget(errorWidget);
card = card.addSection(sections);
// Build and return the Card
return card.build();
}
ไฟล์ Manifest JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "CEL validation example",
"logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "cel_validation_demo",
"state": "ACTIVE",
"name": "CEL Demo",
"description": "Demonstrates CEL Validation",
"workflowAction": {
"inputs": [
{
"id": "value1",
"description": "The first number",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
},
{
"id": "value2",
"description": "The second number",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfig",
"onExecuteFunction": "onExecute"
}
}
]
}
}
}
วิดเจ็ตและการดำเนินการยืนยัน CEL ที่รองรับ
วิดเจ็ตการ์ดที่รองรับการยืนยัน CEL
วิดเจ็ตต่อไปนี้รองรับการยืนยัน CEL
TextInputSelectionInputDateTimePicker
การดำเนินการยืนยัน CEL ที่รองรับ
- การดำเนินการทางคณิตศาสตร์
+: บวกตัวเลขint64,uint64หรือdouble2 ตัว-: ลบตัวเลขint64,uint64หรือdouble2 ตัว*: คูณตัวเลขint64,uint64, หรือdouble2 ตัว/: หารตัวเลขint64,uint64, หรือdouble2 ตัว (การหารจำนวนเต็ม)%: คำนวณค่ามอดุโลของตัวเลขint64หรือuint642 ตัว-: เปลี่ยนตัวเลขint64หรือuint64เป็นค่าลบ
- การดำเนินการทางตรรกะ:
&&: ดำเนินการANDทางตรรกะกับค่าบูลีน 2 ค่า||: ดำเนินการORทางตรรกะกับค่าบูลีน 2 ค่า!: ดำเนินการNOTทางตรรกะกับค่าบูลีน
- การดำเนินการเปรียบเทียบ:
==: ตรวจสอบว่าค่า 2 ค่าเท่ากันหรือไม่ รองรับตัวเลขและรายการ!=: ตรวจสอบว่าค่า 2 ค่าไม่เท่ากันหรือไม่ รองรับตัวเลขและรายการ<: ตรวจสอบว่าตัวเลขint64,uint64หรือdoubleตัวแรกน้อยกว่าตัวที่ 2 หรือไม่<=: ตรวจสอบว่าตัวเลขint64,uint64หรือdoubleตัวแรกน้อยกว่าหรือเท่ากับตัวที่ 2 หรือไม่>: ตรวจสอบว่าตัวเลขint64,uint64หรือdoubleตัวแรกมากกว่าตัวที่ 2 หรือไม่>=: ตรวจสอบว่าตัวเลขint64,uint64หรือdoubleตัวแรกมากกว่าหรือเท่ากับตัวที่ 2 หรือไม่
- การดำเนินการกับรายการ:
in: ตรวจสอบว่ามีค่าอยู่ในรายการหรือไม่ รองรับตัวเลข สตริง และรายการที่ซ้อนกันsize: แสดงผลจำนวนรายการในรายการ รองรับตัวเลขและรายการที่ซ้อนกัน
สถานการณ์การยืนยัน CEL ที่ไม่รองรับ
- ขนาดอาร์กิวเมนต์ไม่ถูกต้องสำหรับการดำเนินการแบบไบนารี: การดำเนินการแบบไบนารี (เช่น
add_int64, เท่ากับ) ต้องใช้อาร์กิวเมนต์ 2 รายการพอดี การระบุจำนวนอาร์กิวเมนต์ที่แตกต่างกันจะทำให้เกิดข้อผิดพลาด - ขนาดอาร์กิวเมนต์ไม่ถูกต้องสำหรับการดำเนินการแบบยูนิแทรี: การดำเนินการแบบยูนิแทรี (เช่น
negate_int64) ต้องใช้อาร์กิวเมนต์ 1 รายการพอดี การระบุจำนวนอาร์กิวเมนต์ที่แตกต่างกันจะทำให้เกิดข้อผิดพลาด - ประเภทที่ไม่รองรับในการดำเนินการทางตัวเลข: การดำเนินการทางตัวเลขแบบไบนารีและแบบยูนิแทรีจะยอมรับเฉพาะอาร์กิวเมนต์ตัวเลขเท่านั้น การระบุประเภทอื่นๆ (เช่น บูลีน) จะทำให้เกิดข้อผิดพลาด
การตรวจสอบฝั่งเซิร์ฟเวอร์
การยืนยันฝั่งเซิร์ฟเวอร์ช่วยให้คุณเรียกใช้ตรรกะฝั่งเซิร์ฟเวอร์ได้โดยการระบุ onSaveFunction() ในโค้ดของขั้นตอน เมื่อผู้ใช้นำทางออกจากบัตรการกำหนดค่าของขั้นตอน onSaveFunction() จะทำงานและช่วยให้คุณยืนยันอินพุตของผู้ใช้ได้
หากอินพุตของผู้ใช้ถูกต้อง ให้แสดงผล saveWorkflowAction
หากอินพุตของผู้ใช้ไม่ถูกต้อง ให้แสดงผลบัตรการกำหนดค่าที่แสดงข้อความแสดงข้อผิดพลาดแก่ผู้ใช้ซึ่งอธิบายวิธีแก้ไขข้อผิดพลาด
เนื่องจากการตรวจสอบฝั่งเซิร์ฟเวอร์เป็นการดำเนินการแบบอะซิงโครนัส ผู้ใช้อาจไม่ทราบข้อผิดพลาดของอินพุตจนกว่าจะเผยแพร่โฟลว์
id ของอินพุตแต่ละรายการที่ผ่านการยืนยันในไฟล์ Manifest ต้องตรงกับ name ของวิดเจ็ตการ์ดในโค้ด
ตัวอย่างต่อไปนี้จะยืนยันว่าอินพุตข้อความของผู้ใช้มีเครื่องหมาย "@"
ไฟล์ Manifest
ข้อมูลบางส่วนของไฟล์ Manifest จะระบุ onSaveFunction() ที่ชื่อ "onSave"
JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Server-side validation example",
"logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "server_validation_demo",
"state": "ACTIVE",
"name": "Email address validation",
"description": "Asks the user for an email address",
"workflowAction": {
"inputs": [
{
"id": "email",
"description": "email address",
"cardinality": "SINGLE",
"required": true,
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfig",
"onExecuteFunction": "onExecute",
"onSaveFunction": "onSave"
}
}
]
}
}
}
โค้ดของแอปพลิเคชัน
โค้ดของขั้นตอนมีฟังก์ชันที่เรียกว่า onSave() ฟังก์ชันนี้จะยืนยันว่าสตริงที่ผู้ใช้ป้อนมี @ หรือไม่ หากมี ฟังก์ชันจะบันทึกขั้นตอน หากไม่มี ฟังก์ชันจะแสดงผลบัตรการกำหนดค่าพร้อมข้อความแสดงข้อผิดพลาดที่อธิบายวิธีแก้ไขข้อผิดพลาด
Apps Script
// A helper method to push a card interface
function pushCard(card) {
const navigation = AddOnsResponseService.newNavigation()
.pushCard(card);
const action = AddOnsResponseService.newAction()
.addNavigation(navigation);
return AddOnsResponseService.newRenderActionBuilder()
.setAction(action)
.build();
}
function onConfig() {
const emailInput = CardService.newTextInput()
.setFieldName("email")
.setTitle("User e-mail")
.setId("email");
const saveButton = CardService.newTextButton()
.setText("Save!")
.setOnClickAction(
CardService.newAction()
.setFunctionName('onSave')
)
const sections = CardService.newCardSection()
.setHeader("Server-side validation")
.setId("section_1")
.addWidget(emailInput)
.addWidget(saveButton);
let card = CardService.newCardBuilder()
.addSection(sections)
.build();
return pushCard(card);
}
function onExecute(event) {
}
/**
* Validates user input asynchronously when the user
* navigates away from a step's configuration card.
*/
function onSave(event) {
console.log(JSON.stringify(event, null, 2));
// "email" matches the input ID specified in the manifest file.
var email = event.formInputs["email"][0];
console.log(JSON.stringify(email, null, 2));
// Validate that the email address contains an "@" sign:
if (email.includes("@")) {
// If successfully validated, save and proceed.
const hostAppAction = AddOnsResponseService.newHostAppAction()
.setWorkflowAction(
AddOnsResponseService.newSaveWorkflowAction()
);
const textDeletion = AddOnsResponseService.newRemoveWidget()
.setWidgetId("errorMessage");
const modifyAction = AddOnsResponseService.newAction()
.addModifyCard(
AddOnsResponseService.newModifyCard()
.setRemoveWidget(textDeletion)
);
return AddOnsResponseService.newRenderActionBuilder()
.setHostAppAction(hostAppAction)
.setAction(modifyAction)
.build();
} else {
// If the input is invalid, return a card with an error message
const textParagraph = CardService.newTextParagraph()
.setId("errorMessage")
.setMaxLines(1)
.setText("<font color=\"#FF0000\"><b>Error:</b> Email addresses must include the '@' sign.</font>");
const emailInput = CardService.newTextInput()
.setFieldName("email")
.setTitle("User e-mail")
.setId("email");
const saveButton = CardService.newTextButton()
.setText("Save!")
.setOnClickAction(
CardService.newAction().setFunctionName('onSave')
)
const sections = CardService.newCardSection()
.setHeader("Server-side validation")
.setId("section_1")
.addWidget(emailInput)
.addWidget(textParagraph) //Insert the error message
.addWidget(saveButton);
let card = CardService.newCardBuilder()
.addSection(sections)
.build();
const navigation = AddOnsResponseService.newNavigation()
.pushCard(card);
const action = AddOnsResponseService.newAction()
.addNavigation(navigation);
const hostAppAction = AddOnsResponseService.newHostAppAction()
.setWorkflowAction(
AddOnsResponseService.newWorkflowValidationErrorAction()
.setSeverity(AddOnsResponseService.ValidationErrorSeverity.CRITICAL)
);
return AddOnsResponseService.newRenderActionBuilder()
.setHostAppAction(hostAppAction)
.setAction(action)
.build();
}
}
หัวข้อที่เกี่ยวข้อง
- กำหนดตัวแปรอินพุต
- บันทึกกิจกรรมและข้อผิดพลาด
- ออบเจ็กต์เหตุการณ์ Workspace Studio
- Common Expression Language (CEL)