Kaizen #99 - Render Widgets Using Client Script

Kaizen #99 - Render Widgets Using Client Script

Hello everyone!
Welcome back to another interesting post. In this post, let us see how you can render Widgets using Client Script.

Widgets are embeddable UI components that you can create and add to your Zoho CRM. You can use widgets to perform functions that utilize data from third-party applications. You can build widgets for Zoho CRM using our JS SDK.

You can render a Widget through Client Script and pass data from the Widget to the Client Script.

Use Case:
At Zylker, a manufacturing company, the Service Agent places orders using the Orders module.  There is a sub-form named Product list. The user should add the products by clicking the "Add row" button every time. 



To avoid this, Zylker wants the users to select multiple products from a single pop-up. Once the user selects the products from that pop-up , the sub-form "Product list" should get updated with all those products(one product in one sub-form row).

Solution:

Whenever the user picks the Product Category, you can create a Client Script to render the widget. The Products selected by the user on the widget , will be passed to the Client Script and will be added as separate rows in  Product list subform.
 
1. Install Zoho CLI and add code to the app folder.
2. Upload the zip file as a Widget.
3. Create a Client Script to render the Widget and to add data to the Sub-form.


1.  Install Zoho CLI and add code to the app folder 

Follow the steps given in this post and add the html code, javascript file and css file.

Index.html



<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Choose products</title>
  <link href="styles/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <div class="wgt_cp_popupContent">
    <section class="wgt_cp_contentWrap">
      <div hidden="true" id="noProductDiv">
        <pre>No products associated to the selected deal</pre>
      </div>
      <table width="100%" cellspacing="0" id="pTable">
        <thead>
          <tr class="wgt_productTblHead">
            <th><input type="checkbox" id="selectAll"     onclick="selectAllProducts(this)"></th>
            <th>Product Name</th>
            <th>Product Category</th>
            <th>Unit Price</th>
            <th>Quantity in Stock</th>
          </tr>
        </thead>
        <tbody id="tbody"></tbody>
      </table>
    </section>
  </div>
  <script src="./script/script.js"></script>
</body>
</html>


Script.js

var count = 0;
var productData, maxRows = 0;
ZOHO.embeddedApp.on("PageLoad", async function (data) {
 console.log("data from Client Script", data);
 maxRows = data.max_rows;
 const search_response = await ZOHO.CRM.API.searchRecord({ Entity: "Products", Type: "criteria", Query: "(Product_Category:equals:" + data.product_category + ")" })
 if (search_response && search_response.data && search_response.data.length) {
  productData = search_response.data;
  var htmlString = "";
  productData.forEach(({ id, Product_Category, Product_Name, Unit_Price, Qty_in_Stock }) => {
   htmlString = htmlString.concat(
    `<tr>
     <td><input type='checkbox' onclick='selected(this)' id='${id}' class='products'></td>
     <td>${Product_Name}</td>
     <td>${Product_Category}</td>
     <td>${Unit_Price}</td>
     <td>${Qty_in_Stock}</td>
    </tr>`
   );
  });
  document.getElementById("tbody").innerHTML = htmlString;
 } else {
  document.getElementById("pTable").hidden = true;
  document.getElementById("noProductDiv").hidden = false;}
});
ZOHO.embeddedApp.init();
function selected(element) {
 element.checked ? count++ : count-- ;
 document.getElementById("selectedCount").innerHTML = `${count} Products selected`;
}
function closewidget() {
 if (count > maxRows) {
  alert("Selected product is greater than the maximum subform rows.");
 } else {
  var selected_products = [];
  for (product_element of document.getElementsByClassName('products')) {
   product_element.checked && selected_products.push(productData.find(product => product.id === product_element.id));}
  console.log("returning to Client Script ...", JSON.stringify(selected_products));
  $Client.close(selected_products);}
}


As per the above script, the products are fetched from the "Products" module based on the "Product Category" selected by the user. This information is captured in "search_response" and is added to the body of  widget.html
Here,  the code $Client.close(selected_products); will pass the selected products from Widget to the Client Script and close the widget rendered from Client Script. Click here for more details about the variable $Client.
Next step is to upload the zip file of the app folder.
Click here to view the complete code.

2. Upload the zip file as a Widget
  • Go to Setup > Developer Space > Widgets.
  • Click Create New Widget.

  • The Hosting should be "Zoho" and mention the html page of the app folder that you uploaded.
Note: The widget should be of "button" type in order to render through a Client Script.

3. Create a Client Script to render Widget and to add data to the subform
  • Go to Setup > Developer Space > Client Script. Click +New Script.
  • Specify the details to create a script and click Next.
  • The Client Script should render the Widget when the user selects Product Category. So Client Script should have field event on the field "Product Category".
  • On the Client Script IDE, you can see the below details.

  • Enter the following script in the Client Script IDE and click save.

var products_list = ZDK.Page.getField('Product_list').getValue();
if (products_list.length === 1) { // Clear subform if empty row
    !Object.values(products_list[0]).every(value => !!value) && products_list.pop();
}
// Open widget with product category & max. allowed rows based on existing subform data
var selected_products = ZDK.Client.openPopup({
    api_name: 'choose_products', type: 'widget', header: 'Choose Products', animation_type: 1, height: '570px', width: '1359px', left: '150px'
}, {
    product_category: value, max_rows: 25 - products_list.length
});
// Update subform with Selected Products from the widget Popup
if (selected_products.length) {
    selected_products.forEach(product => {
        products_list.push({ Product_Name: { id: product.id, name: product.Product_Name }, Quantity: 1, Unit_Price: product.Unit_Price });
    });
  ZDK.Page.getField('Product_list').setValue(products_list);
}


  • To render a widget from Client Script, use openPopup(config, data)  ZDK. You can specify the configuration details like api name of the widget, title, size, animation type as parameters and specify the data to be passed as 'PageLoad' event data in the Widget. 
  • The response from the widget (i.e user selection) is captured by the variable "selected_products". Then each product (id,name,product_name,quantity and unit_price) is pushed to the list products_list. Finally, the product list value  is updated to the Product Category sub-form using setValue(value) ZDK. 
  • Here is how the Widget gets rendered through Client Script.



We hope you found this post useful. We will meet you next week with another interesting topic! If you have any questions let us know in the comment section.

Click here for more details on Client Script in Zoho CRM.


As we approach the 100th post in our Kaizen series next week, we invite you to share your queries and concerns with us.  We are always looking for ways to improve our content and make it more relevant to our readers.

Please fill out this form to share your thoughts.




Happy Coding!




    • Sticky Posts

    • Kaizen #217 - Actions APIs : Tasks

      Welcome to another week of Kaizen! In last week's post we discussed Email Notifications APIs which act as the link between your Workflow automations and you. We have discussed how Zylker Cloud Services uses Email Notifications API in their custom dashboard.
    • Kaizen #216 - Actions APIs : Email Notifications

      Welcome to another week of Kaizen! For the last three weeks, we have been discussing Zylker's workflows. We successfully updated a dormant workflow, built a new one from the ground up and more. But our work is not finished—these automated processes are
    • Kaizen #152 - Client Script Support for the new Canvas Record Forms

      Hello everyone! Have you ever wanted to trigger actions on click of a canvas button, icon, or text mandatory forms in Create/Edit and Clone Pages? Have you ever wanted to control how elements behave on the new Canvas Record Forms? This can be achieved
    • Kaizen #142: How to Navigate to Another Page in Zoho CRM using Client Script

      Hello everyone! Welcome back to another exciting Kaizen post. In this post, let us see how you can you navigate to different Pages using Client Script. In this Kaizen post, Need to Navigate to different Pages Client Script ZDKs related to navigation A.
    • Kaizen #210 - Answering your Questions | Event Management System using ZDK CLI

      Hello Everyone, Welcome back to yet another post in the Kaizen Series! As you already may know, for the Kaizen #200 milestone, we asked for your feedback and many of you suggested topics for us to discuss. We have been writing on these topics over the
    • Recent Topics

    • How to get Monday as 1st day of the week?

      Hi, The first day of the week is Sunday in Zoho Creator calendar.So it is hardly usable as in Europe the 1st of the week is always Monday. How can I get Monday as 1st day of the week? Best regards, Chris
    • What's New - April 2025 | Zoho Backstage

      Hello there, Phew! It’s been a busy month—and it’s all for you. You know that feeling when your to-do list is long, your coffee’s gone cold, but your team is absolutely crushing it behind the scenes? That’s been us this month. Between brainstorming, building,
    • Mi cámara se desconecta permanentemente.

      Buenos días. Tengo una cámara web de última generación. En concreto el modelo W4DS de VIZOLINK. Realiza una primera conexión pero después se desconecta con el mensaje de que no es compatible con ZOHO. Me extraña mucho que una aplicación tan reciente cometa
    • Overall unsubscribes from mailing/contact lists

      Hi, I’m looking to track how many people are unsubscribing from our mailing/contact lists overall — not just from individual campaigns. Is there a way to access this total unsubscribe number on a weekly basis for internal reporting? Thanks in advanc
    • Tips and Tricks #40: Find and add YouTube videos to your slide from within Show

      Hi Everyone!  When using the right videos in a presentation, you can easily capture your audience's attention and help them connect with your message. This is useful especially when you want to explain any complex concept. For example, you can use a video
    • I want to add a button in Zoho Creator that, when clicked, opens a Zoho authorization window and then redirects to my website to obtain API tokens.

      Here's the translation of your text into English: "I want to add a button in Zoho Creator that, when clicked, opens a Zoho authorization window and then redirects to my website to obtain API tokens. When running in the developer environment, I get the
    • Enhance Data Visibility with Mapping Fields from Lookup Module

      We’re thrilled to announce an exciting new feature in Zoho Recruit: Mapping Fields from Lookup Module! This powerful addition is designed to display additional details from a related module when using lookup fields. This enhances data visibility and provides
    • Feature Request – Support for Stripe Direct Debit for Canadian Customers in Zoho Books

      I’d like to request support for Stripe Direct Debit as a payment option for Canadian customers within Zoho Books. Currently, while Stripe credit card payments are supported for Canadian businesses, there is no option to enable Direct Debit (ACH/EFT) through
    • Form fields appearing twice on creator mobile

      We have a custom application created in Zoho Creator. When we look at the application form on desktop everything looks normal. Whenever we access the application on Creator Mobile App some fields appear twice instead of only ones. I provided an example
    • Creator Widget using values from Creator Form on the same page

      Hi all, I have a widget I'm working on that I'd like to use values from a form that's on the same page as the widget. I have something working right now, where I have a stateless form on a page. On input to the form I load an inner page, setting query
    • Smart Hiring Made Easy: Experience our Optimized Chatbot

      We're thrilled to announce that Zoho Recruit's Chatbot has received an exciting update! With this enhancement, recruiters will have access to even more features that will help them passively find the best candidates for their open positions. Listed below
    • `insert into` Always Fails with “Improper Statement” — Even with Minimal Code

      Im develeping my inventory database using ChatGPT to help me and I´m running into an issue in my scan inventory form script when I try to make a form for logging the scanned items. 🆘 Zoho Creator: `insert into` Always Fails with “Improper Statement”
    • I want to know the gross profit by sales person. How?

      Kindly guide me how to know the amount of gross profit which is calculated on the basis of sales person. That means, how much is the amount of gross profit made by a particular sales person.
    • ZOHO CRM Lead_Status_History

      Hi, ZOHO CRM Lead_Status_History table is showing only ID and Modified Date. I want the history of status change in CRM Lead
    • Zoho Writer page break in a merge repeating region always adds an unwanted blank page

      Hi I'm merging a Zoho CRM record to a Zoho Writer document with a repeating region to display subform records on their own page within the document. When I try to insert a page break in a repeating region, the resulting merge always adds an unwanted blank
    • Creating a grid of worker activity in Zoho analytics

      Hi, We provide medical services to patients and billing is time based. We want to create a filterable grid in which we can look at any month by day and any worker and how many minutes of billable activity they performed by patient. I know exactly what
    • Power of Automation :: Automatically start / pause / stop timer on task status update.

      Hello Everyone, A Custom function is a user-written set of code to achieve a specific requirement. Set the required conditions needed as when to trigger using the Workflow rules (be it Tasks / Project) and associate the custom function to it. Requirement:-
    • Restrict users on Form Submission

      In Zoho Creator, is there a way to restrict users/customers on form submission, on-click event of the submit button, they will be redirected to the customer login portal page (where they sign in / sign up) to complete a service purchase. We want a common
    • Update date field custom module using Zoho Inventory Update Record

      I'm trying to update a date field in a custom module inside zoho inventory but keep getting this error: "code": 6, "message": "syntax.error.invalid.json" This is how my code looks: campo_sku = Map(); campo_sku.put("cf_sku_master",i_sku); campo_sku.put("cf_sku_common",i_sku_common);
    • Are we able to bring FontAwesome icons into a Zoho Page?

      The OOTB Zoho icons are insufficient. Also, are we able to pull in standard emojis?
    • CRM Hack #3: How to update formula functions for already created records.

      Hello everyone! It’s Wednesday and we are back with yet another hack.. I'm sure you've used formula fields to meet some requirements specific to your business. Let's consider an example each for external (customer-facing) and internal facing scenarios
    • Inventory Blocking for serial number tracking.

      Hi We are using multiple channels to get orders which adds the product to committed stock. But is there a method to block serial number of products based on FIFO automatically when an order is created, or when SO is approved?
    • CRM List view for text fields that check "Does not start with" or "Does not end with"

      So these filter options are available when making reports and such, but they don't seem be available when creating a filtered view.  The text filter options there are are: "contains", "does not contain", "starts with", "ends with". Is there an easy technique to recreate the "Does not start with" and "Does not end with" functionality that I'm missing?
    • Is PageSense included in Zoho One?

      PageSense is marketed as part of the Zoho One product suite, but when I login to PageSense it prompts me to upgrade (in 31 days I suppose) even though I am on a Zoho One subscription. Is PageSense included or not? If not, then please don't market it as
    • [Product Update] Introduction of Task Lists Module in Zoho Projects Integration

      Dear Customers, As part of our ongoing efforts to enhance our integrations, we’re introducing support for the "Task Lists" module in the Zoho Projects integration with Zoho Analytics. Currently, Task List-related information is available within the Tasks
    • Marketing Automation Access

      Hello, Is anyone having issues getting started with Marketing Automation? I keep getting an internal error during the start up screens. I've been trying and it hasn't been resolved in a week. Is the app worth waiting for or should I just use campaigns?
    • Best Way to Integrate a Shared Sales Inbox with Zoho CRM

      I’m setting up a shared email inbox (e.g., sales@mycompany.com) for our sales team and want to integrate it with Zoho CRM Leads and Deals so that multiple team members can collaborate efficiently. Since Zoho CRM doesn’t support IMAP for shared inboxes,
    • 【Zoho CRM】詳細ページからサブフォーム行追加の禁止

      ■概要 いつの時点からか確認ができなかったのですが、サブフォームの行を編集ページではなく詳細ページから直接追加出来るようになっていました。便利な機能追加なのですが、サブフォームでクライアントスクリプトを使ってフィールドの読み取り専用設定などをしている環境だと、詳細ページから行挿入されるとクライアントスクリプトが動作しないので想定していたフィールドの読み取り専用設定が効かない状態になってしまいます。クライアントスクリプトを使って、詳細ページから行挿入されると保存できないようにすることで間接的に詳細ページから行挿入を禁止する方法をご紹介します。
    • The Social Wall: April 2025

      Hey everyone, Welcome to the April edition of the Social Wall, where we keep you in loop about the latest feature updates, changes, and more. Let's see how April went by: Manage and respond to comments on your Threads posts from Inbox With the latest
    • link non- VAT tax invoice to Fatoora portal

      Hi all Actually I have VAT tax invoice and non- VAT tax invoice About VAT tax invoice I have no problem I can link any invoice to Fatoora portal But the problem in the non VAT tax invoice because I have customers outside of Saudi Arabia No VAT ID no CRN
    • Pdf/A-3 ( embedded with xml)

      Mr. Abdur rahman, Please give me answer of my questions. Does your software generate PDF/A-3 (with embedded XML) and XML formats, fully compliant with ZATCA Phase 2 for B2B invoices? Are Phase 2 fields (e.g., UUID, Previous Invoice Hash, Invoice Counter
    • Updating field from the UI or from function take more that 1 minute to be updated

      I have activity order model with dropdown status field, I've changed the status from Completed to Canceled on the CRM like on the attached image: But once I fetch the record on function the record didn't updated behind the scene The strange thing in here
    • Zoho Voice & Zoho CRM

      I was using Twillio to send automated messages to my clients when a new lead comes in Zoho CRM. The twillio integration was stopped by Zoho and hence I used Zoho Telephony which doesn't support SMS. Now someone from Zoho told me to use Zoho Voice. I bought
    • Import contacts - invalid pattern with encrypted emails

      Hello, I have a list of encrypted emails provided by an external partner. They need to be imported into a custom list. Problem is, the import process is ignoring the entire list, maybe because of the weird format? Since they are encrypted, they all look like this example: d+NDd5wqi3neiQWEwquie1bnwquien@example.com What can I do to import this list? Also, is there a way to allow my user to add contacts without this "ignore filter" from now on? The fact is that our partner will provide us a new list
    • Important: Microsoft Outlook Bulk Email Updates

      Dear Marketers, We want to bring your attention to an important upcoming change announced by Microsoft (Outlook) that will impact users sending bulk emails to Outlook.com, Hotmail.com, and other Microsoft-hosted inboxes. This update focuses on strengthening
    • UI and other enhancements in Community module

      Hello everyone, The Community module has undergone a UI revamp to improve user experience. In addition, we have introduced Status Board and Bulk Approval of posts to provide better engagement. Improved User Interface The new interface brings the following
    • Add Pre-Trigger Filter Capability for Webhook Triggers in Zoho Flow

      Dear Zoho Flow Team, Greetings, We’ve been working extensively with Zoho Flow and appreciate the flexibility it offers for automation across our tools. We’d like to request a feature enhancement specifically related to Webhook triggers: Use Case: Currently,
    • Getting data from subforms

      Bonjour, I have a Product form that has a subform with 2 fields : Unit (Kg, boxes...) and Price. In an Order form, I select an item from Product, and I already managed to input the Unit choices in a dropdown field with the following script: RefProduit
    • Support for Transparent, Shadowless Panels in Zoho Creator Pages

      Hi Zoho Creator Team, Hope you're doing well. We would like to request more design flexibility in Zoho Creator, specifically the ability to create panels with no background, border, or shadow. Use Case: In our app, we’re designing a dashboard that uses
    • Looping issues

      Can someone please explain why this doesn't infinitely loop, but the second one does? How can I get around this? This one loops ⬇️
    • Next Page