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

    • Autotranslate only have 2 of my 3 languages

      My HelpCenter has three languages, as you can see below: I chose to use Google Translate for my automatic translations: I can only see 2 languages: How do I add the Portuguese here? Is this a bug? Thank you.
    • Como se guardan las imagenes que se cargan desde el Zoho Forms a Drive o Workdrive

      ¿Cómo puedo usar Zoho Flow para tomar un archivo subido en un formulario de Zoho Forms, extraer su ID de la URL y luego copiar ese archivo a una carpeta específica en Zoho WorkDrive de manera automatizada?
    • Record Summary Template Improvements

      Hi, Just a few suggestions to improve the usage of record summary templates. Some of them have been asked for before. Dynamic renaming of templates when sent as pdf attachment in sendmail task, also on export to pdf. Option for Page numbering. Option to add current date (${zoho.currentdate}) Option to repeat header and footer on each page. Subforms, more options in "Related Field Properties" for cell borders.(Currently only turns full border on or off)  Choose template to use as record summary from
    • In Zoho people Check in report the date want come as Colum how i can achive that in zoho people or analytics

      In Zoho people Check in report the date want come as Colum. How i can achive that in zoho people or analytics
    • How to customize member portal invite

      Hello, when I sent an invite to users to join member portal, here what they get below. Is there a template to edit or way to change how this mail being sent? I checked /zstore/settings/notification but unfortunately there is no invite mail template here.
    • Publish directly to production

      Hello! I am wondering if there is a way to publish changes directly to the production version of an application?
    • Infinite phone verification loop

      Hi, I'm trying to test your Mail service, but I am unable to due to a problem with the phone verification. I've correctly received the verification code and verified my phone number, but whenever trying to access the Mail portal in Zoho I am presented
    • how to do bulk delete for Zoho Desk tickets?

      how to do bulk delete for Zoho Desk tickets? The old UI has this function and now i cannot find it on the new UI. 
    • Workflows being applied and the Large unwanted popup

      When a workflow is being applied do to an action, then the Agent is left with a large Window asking if they would like the see the changes this workflow did. Is there any way to disable this prompt from appearing?
    • Urgent: Amazon Login Block Issue via Zoho – Suspected Integration Problem

      We’re currently experiencing a critical issue related to our Amazon login through Zoho. Although the client can still access the Amazon Seller Central account directly, our team is being blocked when trying to log in via Zoho. The account itself is not
    • Delete a lot of entries...

      Hi!, I synchronized a lot of accounts from my CRM and now I would like to delete them all. How to delete more than 50 accounts at once? Thx
    • Automatically create support tickets on a recurring basis

      As mentioned in this post, the idea of a recurring ticket is pretty valid. From time to time, we have to create repetitive tickets (like windows update tasks, restore simulation of backups, check firewall rules for unused entries, and so on). I guess
    • Update Zoho Sign Mobile View?

      Hello, My clients have have difficulty seeing the Zoho Sign documents while viewing on their mobile devices. The font is small and it is difficult for them to navigate. My use cases for using Zoho Sign are almost exclusively completed on a mobile device
    • AI secretary

      In our company, Claude is the secretary and creates inquiries and schedules from Gmail. You no longer have to enter them yourself. The secret is that we created an MCP server that connects to CRM. https://x.com/Mac_nishio/status/1917954562566328694
    • CRM Account Owner to be Assigned as Customer Owner

      We have enabled books and CRM integration The Account Owner in CRM, should be assigned as the Customer Owner in Books, but this is not the case You have go to books and manually assign the Customer Owner again If you change the Account Owner in CRM, again
    • We are unable to process your request at the moment. Kindly contact our support team at support.me@zohobooks.com for further assistance.

      if i need post any invoice i show this We are unable to process your request at the moment. Kindly contact our support team at support.me@zohobooks.com for further assistance.
    • Zoho Books Contact Creation through API.

      I tried creating a contact using API with following payload. Sun Apr 6 08:28:03 2025 [186723][1][FATAL] Array ( [10002] => https://www.zohoapis.com/books/v3/contacts?organization_id=763906850 [19913] => 1 [10102] => [68] => 10 [13] => 30 [84] => 2 [10036]
    • How Would I get data from a network drive to be feed into creator program.

      What's the easiest and cleanest solution for this?
    • Fetching a missing Folder, now creates it

      Hello, I'm using Zoho Flow to fetch a folder within a Team Folder. If the folder is missing (folder ID is null), I trigger a Create Folder. Now in 2025, when I fetch a missing folder, a folder is created right away with the "name + full date" and a Folder
    • Company Name Update and Chatbot Customization

      We would like to request your assistance with the following updates to our Zoho system: Company Name Change: we have integrated chatbot on our website. Please help to change our company name from BVK Infrasoft to BVK Group on chatbot the entire system,
    • How does BadgeUp Work?

      When creating the badges, where do you all get those printed? especially if you use the plastic type badges. Does Zoho send the files out or do some kind of integration with a 3rd party badge printer? I'm on a ZohoOne subscription and didn't want to use my one license for a test event to see how this worked. Thanks for any insight Randall
    • Custom Script for Validation Rules

      In the Validation Rules I would like to have custom functions, we can do that in Zoho CRM and its really useful There are some custom fields in Sales Orders and Purchase Order Modules We are using Zoho Books With our internal apps, and we need to put
    • Invoicing from Saudi Arabia to other countries

      Team, i would like to know if i can invoice the partner in Tunisia as i am not able to push the invoice without Arabic name and National address to the Fatoora Portal which is a mandate
    • I want to change a User's role in zoho but it is giving me an error.

      Hi, I want to change a User's role in zoho but it is giving me an error - You cannot change the role of this user as the user's credentials are being used for the integration with Zoho CRM. Assign the super admin role to another user in Zoho CRM, click
    • upload attachment to Zoho books bill from Zoho CRM

      Hello I have a document stored in a file field in CRM (module reservation) I am trying to attach this document to the bill created in Zbooks using Deluge, but I keep having issue, either File is empty or {"code":2,"message":"The request passed is not
    • Zero in the Invoice Amount Text field is adding onto the figures entered.

      Hi Zoho, This is very small & minute error, but it gets the users irritated. While entering values in amount column of the Invoice the zero which was earlier present there by default will still add on to the figures entered, for suppose if we want to
    • The buying of forign currency

      Hello We had buying USD for AED. Those were bank transfers from a first bank account to a second with bank's exchange rates. We have chosen for those transactions category "The buying of forign currency" and putted bank's exchange rate. Is it correct
    • الخصم على مستوى فاتورة المبيعات

      السلام عليكم ورحمة الله وبركاته مطلوب في إنشاء خصم على مستوى فاتورة المبيعات وليس على مستوى البند أريد معرفة الطريقة؟
    • Having problems invoking Workdrive API via ClientScript

      I'm having problems creating a folder in Workdrive. The connection is invoked successfully, but I get the following return message: {"_keyModified":{},"_status":"error","_code":"SUCCESS","_message":"Invoke action failed","_details":{"statusMessage":"Invalid
    • Give Permission for User test in Development/Staging modes

      Hi Everyone, I am using Zoho Creator C6. Where there are development and staging modes. Is it possible to give special / temporary permission for users to test directly in development and staging? Or do you have any other ideas? Thank you very much.
    • Add Date_of_Last_Purchase custom Function

      I am looking for a way to create a simple custom function that will execute when a new sales order is created. The function will set a custom field on the customer called "Date_Last_Purchase" to the current date. So as ever new sales order comes in for
    • Failed job notifications

      Is there are way to receive an alert when a job has failed? If not this would be a useful feature.
    • Option to separate First Name and Last Name into separate columns in entry reports

      It would be great if there was a way to show First Name and Last Name as separate columns in Zoho Forms entry reports. At the moment First Name and last name are combined together in reports and this means I need to create a formula in Excel/Sheet to
    • default reply email

      In the zoho mail application you can make another email your default email address.  So when you compose a new email it defaults to the email address you have set.  However this functionality does not work when you reply to an email.  you can select the email from a drop down, but I wanted to know if their is a way to set the reply email button as a different default email, just like the compose functionality.  An example:  I write an email from my zoho email account to a client witch show the sender
    • Import CRM Vendor Module for Mail Merge

      Hello, It seems I cannot import the vendor module field for a merge document? Is there a way to turn this on?  I have the ability to import my custom module fields, but not standard built-in CRM modules like Vendors.  Am I missing something? Thank you very much for your assistance!
    • Error in SalesIQ Chatbot: "Add Ticket" Card Fails with "Error" Route

      Hello Zoho Community, I'm encountering an issue with my Zoho SalesIQ chatbot. Previously, when the conversation flow reached the "Add Ticket" card, it successfully created a ticket in Zoho Desk. However, recently, upon reaching this card, the flow follows
    • Merging 2 tickets

      Hi I understand how to merge 2 tickets already but find the process quite cumbersome. It is not always simple to perform a search that causes the 2 tickets in question to show up on the Ticket Screen, and this is the only place a merge can be performed. Doing a search for the customer or contact linked to the ticket displays all of their tickets which could be hundreds to sort through, you could do a custom search that only shows open tickets but doing that every time is also time consuming. Not
    • Can’t Send Outgoing Mail

      Hello, one of the email addresses on my account had its outgoing mail privileges blocked. This was due to some bot signups on my website, causing my email to send a bunch of undeliverable emails. I have corrected this issue on my website. Please restore
    • Efficient way to get a list of records like Notes under Leads that changed in last N minutes

      Hi, I am writing a process to consume the Zoho Leads and put it in an internal system. For Leads, Accounts and Contacts, the getRepords with lastModifiedTime works great as I can call the API to get only the updated records say in last 30 minutes. However
    • IMAP Connection Issue – "Disconnect called before connection setup" (Zoho + Freshdesk Integration)

      Hello, Since April 25, 2025, we are facing a critical issue with our Zoho Mail integration with Freshdesk. Incoming emails are no longer being received in Freshdesk. Freshdesk Support has confirmed that their system is trying to connect to our Zoho mailbox,
    • Next Page