একটি ইনপুট ভেরিয়েবল যাচাই করুন

এই নির্দেশিকায় একটি ইনপুট ভেরিয়েবল যাচাই করার পদ্ধতি ব্যাখ্যা করা হয়েছে।

ইনপুট ভেরিয়েবল নির্ধারণ করার সময়, একটি উত্তম অনুশীলন হিসেবে, ব্যবহারকারী একটি উপযুক্ত মান প্রবেশ করিয়েছে কিনা তা যাচাই করে নিন। উদাহরণস্বরূপ, যদি আপনি ব্যবহারকারীকে একটি সংখ্যা ইনপুট করতে বলেন, তবে তারা 1 প্রবেশ করিয়েছে কিনা a যাচাই করলে নিশ্চিত হওয়া যায় যে আপনার ধাপটি কোনো ত্রুটি ছাড়াই সম্পন্ন হয়েছে।

একটি ইনপুট ভেরিয়েবল যাচাই করার দুটি উপায় আছে:

  • ক্লায়েন্ট-সাইড ভ্যালিডেশন : ক্লায়েন্ট-সাইড ভ্যালিডেশনের মাধ্যমে, আপনি ব্যবহারকারীর ইনপুট সরাসরি তার ডিভাইসে যাচাই করতে পারেন। ব্যবহারকারী তাৎক্ষণিক প্রতিক্রিয়া পান এবং ধাপটি কনফিগার করার সময় তার ইনপুটের যেকোনো ভুল সংশোধন করতে পারেন।
  • সার্ভার-সাইড ভ্যালিডেশন : সার্ভার-সাইড ভ্যালিডেশন আপনাকে যাচাইকরণের সময় সার্ভারে লজিক চালানোর সুযোগ দেয়, যা তখন কাজে আসে যখন ক্লায়েন্টের কাছে নেই এমন তথ্য, যেমন অন্যান্য সিস্টেম বা ডেটাবেসের ডেটা, খুঁজে বের করার প্রয়োজন হয়।

ক্লায়েন্ট-সাইড যাচাইকরণ

ক্লায়েন্ট-সাইড ভ্যালিডেশন বাস্তবায়নের দুটি উপায় রয়েছে:

  • সাধারণ যাচাইকরণের জন্য, যেমন কোনো উইজেটে নির্দিষ্ট সংখ্যার চেয়ে কম অক্ষর আছে কিনা বা তাতে @ চিহ্নটি আছে কিনা তা যাচাই করার জন্য, Google Workspace অ্যাড-অনের Card সার্ভিসের Validation ক্লাসটি চালু করুন।
  • শক্তিশালী যাচাইকরণের জন্য, যেমন একটি উইজেটের মানের সাথে অন্য উইজেটের মানের তুলনা করার জন্য, আপনি CardService ব্যবহার করে নিম্নলিখিত সমর্থিত কার্ড উইজেটগুলিতে কমন এক্সপ্রেশন ল্যাঙ্গুয়েজ (CEL) যাচাইকরণ যোগ করতে পারেন।

Validation ক্লাসটি আহ্বান করুন

নিম্নলিখিত উদাহরণটি যাচাই করে যে একটি TextInput উইজেটে ১০টি বা তার কম অক্ষর রয়েছে:

অ্যাপস স্ক্রিপ্ট

const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
    CardService.InputType.TEXT);

অতিরিক্ত যাচাইকরণ বিকল্পের জন্য CEL যাচাইকরণ ব্যবহার করুন।

CEL বৈধতা

কমন এক্সপ্রেশন ল্যাঙ্গুয়েজ (সিইএল) ভ্যালিডেশন, অন্যান্য সার্ভিস থেকে ডেটা খোঁজার ওপর নির্ভরশীল নয় এমন ইনপুট ভ্যালু চেকের কাজ ক্লায়েন্ট সাইডে অফলোড করার মাধ্যমে, সার্ভার-সাইড ভ্যালিডেশনের বিলম্ব ছাড়াই তাৎক্ষণিক ইনপুট চেকের সুবিধা প্রদান করে।

আপনি CEL ব্যবহার করে কার্ডের আচরণও তৈরি করতে পারেন, যেমন ভ্যালিডেশনের ফলাফলের উপর নির্ভর করে কোনো উইজেট প্রদর্শন করা বা লুকানো। এই ধরনের আচরণ একটি ত্রুটির বার্তা দেখানো বা লুকানোর জন্য উপযোগী, যা ব্যবহারকারীদের তাদের ইনপুট সংশোধন করতে সাহায্য করে।

একটি সম্পূর্ণ CEL ভ্যালিডেশন তৈরিতে নিম্নলিখিত উপাদানগুলো অন্তর্ভুক্ত থাকে:

  • কার্ডের ExpressionData : এতে নির্দিষ্ট ভ্যালিডেশন লজিক এবং সংজ্ঞায়িত শর্তগুলোর কোনো একটি পূরণ হলে উইজেট ট্রিগার করার লজিক থাকে।

    • Id : বর্তমান কার্ডের মধ্যে থাকা ExpressionData জন্য একটি অনন্য শনাক্তকারী।
    • Expression : CEL স্ট্রিং যা ভ্যালিডেশন লজিক নির্ধারণ করে (যেমন, "value1 == value2" )।
    • Conditions : শর্তাবলীর একটি তালিকা যাতে পূর্বনির্ধারিত যাচাইকরণের ফলাফলের (সফল বা ব্যর্থ) একটি নির্বাচন থাকে। শর্তাবলী একটি সাধারণ actionRuleId সহ Triggers মাধ্যমে উইজেট-সাইডের EventAction সাথে সংযুক্ত থাকে।
    • কার্ড-স্তরের EventAction : পোস্ট-ইভেন্ট ট্রিগারের মাধ্যমে কার্ডে CEL ভ্যালিডেশন সক্রিয় করে এবং রেজাল্ট উইজেটগুলির সাথে ExpressionData ফিল্ডকে সংযুক্ত করে।
      • actionRuleId : এই EventAction এর অনন্য আইডি।
      • ExpressionDataAction : এই অ্যাকশনটি CEL ইভ্যালুয়েশন শুরু করে তা বোঝাতে START_EXPRESSION_EVALUATION এ সেট করুন।
      • Trigger : actionRuleId এর উপর ভিত্তি করে Conditions উইজেট-সাইড EventActions সাথে সংযুক্ত করে।
  • উইজেট-স্তরের EventAction : সফল বা ব্যর্থ শর্ত পূরণ হলে ফলাফল উইজেটের আচরণ নিয়ন্ত্রণ করে। উদাহরণস্বরূপ, একটি ফলাফল উইজেট একটি TextParagraph হতে পারে, যাতে একটি ত্রুটির বার্তা থাকে যা শুধুমাত্র ভ্যালিডেশন ব্যর্থ হলেই দৃশ্যমান হয়।

    • actionRuleId : কার্ড-সাইডের Trigger এর actionRuleId সাথে মেলে।
    • CommonWidgetAction : এমন সব অ্যাকশন সংজ্ঞায়িত করে যেগুলিতে মূল্যায়নের প্রয়োজন হয় না, যেমন উইজেটের দৃশ্যমানতা আপডেট করা।
      • UpdateVisibilityAction : এমন একটি অ্যাকশন যা কোনো উইজেটের দৃশ্যমানতার অবস্থা (VISIBLE বা HIDDEN) আপডেট করে।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে দুটি টেক্সট ইনপুট সমান কিনা তা পরীক্ষা করার জন্য CEL ভ্যালিডেশন প্রয়োগ করতে হয়। যদি সেগুলি সমান না হয় তবে একটি ত্রুটির বার্তা দেখানো হয়।

  • যখন failCondition পূরণ হয় (ইনপুটগুলো সমান না হলে), তখন এরর মেসেজ উইজেটটি দৃশ্যমান হয়ে প্রদর্শিত হয়।
    চিত্র ১: যখন failCondition পূরণ হয় (ইনপুটগুলো সমান না হলে), তখন এরর মেসেজ উইজেটটি VISIBLE হয়ে প্রদর্শিত হয়।
  • যখন সফলতার শর্ত পূরণ হয় (ইনপুটগুলো সমান হয়), তখন ত্রুটির বার্তা উইজেটটি লুকানো (HIDDEN) হয়ে যায় এবং প্রদর্শিত হয় না।
    চিত্র ২: যখন successCondition পূরণ হয় (ইনপুটগুলো সমান হয়), তখন ত্রুটির বার্তা উইজেটটি লুকানো HIDDEN হয়ে যায় এবং প্রদর্শিত হয় না।

এখানে উদাহরণ অ্যাপ্লিকেশন কোড এবং JSON ম্যানিফেস্ট ফাইল দেওয়া হলো:

অ্যাপস স্ক্রিপ্ট

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();
}

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 ভ্যালিডেশন সমর্থন করে:

  • TextInput
  • SelectionInput
  • DateTimePicker

সমর্থিত CEL বৈধতা অপারেশন

  • গাণিতিক ক্রিয়াকলাপ
    • + : দুটি int64 , uint64 , বা double সংখ্যা যোগ করে।
    • - : দুটি int64 , uint64 , বা double সংখ্যা বিয়োগ করে।
    • * : দুটি int64 , uint64 , বা double সংখ্যাকে গুণ করে।
    • / : দুটি int64 , uint64 , বা double সংখ্যাকে ভাগ করে (পূর্ণসংখ্যার ভাগ)।
    • % : দুটি int64 বা uint64 সংখ্যার মডিউলো নির্ণয় করে।
    • - : একটি int64 বা uint64 সংখ্যাকে বাতিল করে।
  • যৌক্তিক ক্রিয়াকলাপ:
    • && : দুটি বুলিয়ান মানের উপর লজিক্যাল AND অপারেশন সম্পাদন করে।
    • || : দুটি বুলিয়ান মানের উপর লজিক্যাল OR অপারেশন সম্পাদন করে।
    • ! : বুলিয়ান মানের উপর লজিক্যাল NOT অপারেশন সম্পাদন করে।
  • তুলনা কার্যক্রম:
    • == : দুটি মান সমান কিনা তা যাচাই করে। সংখ্যা এবং তালিকা সমর্থন করে।
    • != : দুটি মান সমান নয় কিনা তা যাচাই করে। সংখ্যা এবং তালিকা সমর্থন করে।
    • < : প্রথম int64 , uint64 , বা double সংখ্যাটি দ্বিতীয়টির চেয়ে ছোট কি না, তা যাচাই করে।
    • <= : প্রথম int64 , uint64 , বা double সংখ্যাটি দ্বিতীয়টির চেয়ে ছোট বা সমান কিনা তা পরীক্ষা করে।
    • > : প্রথম int64 , uint64 বা double সংখ্যাটি দ্বিতীয়টির চেয়ে বড় কি না, তা যাচাই করে।
    • >= : প্রথম int64 , uint64 , বা double সংখ্যাটি দ্বিতীয়টির চেয়ে বড় বা সমান কিনা তা যাচাই করে।
  • তালিকা কার্যক্রম:
    • in : কোনো ভ্যালু একটি লিস্টে আছে কি না তা যাচাই করে। এটি সংখ্যা, স্ট্রিং এবং নেস্টেড লিস্ট সমর্থন করে।
    • size : একটি তালিকার আইটেমের সংখ্যা ফেরত দেয়। এটি সংখ্যা এবং নেস্টেড তালিকা সমর্থন করে।

অসমর্থিত CEL বৈধতা পরিস্থিতি

  • বাইনারি অপারেশনের জন্য আর্গুমেন্টের ভুল সংখ্যা : বাইনারি অপারেশনের (যেমন, add_int64 , equals) জন্য ঠিক দুটি আর্গুমেন্ট প্রয়োজন। ভিন্ন সংখ্যক আর্গুমেন্ট দিলে একটি ত্রুটি দেখা দেবে।
  • ইউনারি অপারেশনের জন্য আর্গুমেন্টের ভুল সংখ্যা : ইউনারি অপারেশনের (যেমন, negate_int64 ) জন্য ঠিক একটি আর্গুমেন্ট প্রয়োজন। ভিন্ন সংখ্যক আর্গুমেন্ট দিলে একটি ত্রুটি দেখা দেবে।
  • সংখ্যাসূচক অপারেশনে অসমর্থিত টাইপ : সংখ্যাসূচক বাইনারি এবং ইউনারি অপারেশন শুধুমাত্র সংখ্যা আর্গুমেন্ট গ্রহণ করে। অন্য টাইপ (যেমন, বুলিয়ান) প্রদান করলে একটি ত্রুটি দেখা দেবে।

সার্ভার-সাইড যাচাইকরণ

সার্ভার-সাইড ভ্যালিডেশনের মাধ্যমে, আপনি আপনার স্টেপের কোডে onSaveFunction() উল্লেখ করে সার্ভার-সাইড লজিক চালাতে পারেন। যখন ব্যবহারকারী স্টেপের কনফিগারেশন কার্ড থেকে অন্য কোথাও চলে যান, তখন onSaveFunction() রান করে এবং আপনাকে ব্যবহারকারীর ইনপুট যাচাই করার সুযোগ দেয়।

যদি ব্যবহারকারীর ইনপুট বৈধ হয়, তাহলে saveWorkflowAction রিটার্ন করুন।

যদি ব্যবহারকারীর ইনপুট অবৈধ হয়, তাহলে একটি কনফিগারেশন কার্ড ফেরত দিন যা ব্যবহারকারীকে একটি ত্রুটি বার্তা প্রদর্শন করে এবং ত্রুটিটি কীভাবে সমাধান করতে হবে তা ব্যাখ্যা করে।

যেহেতু সার্ভার-সাইড ভ্যালিডেশন অ্যাসিঙ্ক্রোনাস, তাই ব্যবহারকারী তাদের ফ্লো পাবলিশ না করা পর্যন্ত ইনপুট ত্রুটি সম্পর্কে জানতে নাও পারেন।

ম্যানিফেস্ট ফাইলে থাকা প্রতিটি যাচাইকৃত ইনপুটের id অবশ্যই কোডে থাকা কার্ড উইজেটের name সাথে মিলতে হবে।

নিম্নলিখিত উদাহরণটি যাচাই করে যে ব্যবহারকারীর টেক্সট ইনপুটে "@" চিহ্নটি অন্তর্ভুক্ত আছে কিনা:

ম্যানিফেস্ট ফাইল

ম্যানিফেস্ট ফাইলের উদ্ধৃতাংশে "onSave" নামের একটি onSaveFunction() নির্দিষ্ট করা হয়েছে:

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() নামে একটি ফাংশন রয়েছে। এটি ব্যবহারকারীর দেওয়া স্ট্রিং-এ @ চিহ্নটি আছে কিনা তা যাচাই করে। যদি থাকে, তবে এটি ধাপটি সংরক্ষণ করে। আর যদি না থাকে, তবে এটি একটি ত্রুটি বার্তা সহ একটি কনফিগারেশন কার্ড ফেরত দেয়, যেখানে ত্রুটিটি কীভাবে সমাধান করতে হবে তা ব্যাখ্যা করা থাকে।

অ্যাপস স্ক্রিপ্ট

// 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();
  }
}