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

    • Nested notebooks

      Dear Sir/Madam, I would like to know if it is possible to nest notebooks. It would be very helpful when there are too many, as it would improve organization. Thank you for your response. Best regards.
    • Third Insight - The Importance of Data Segregation

      The Wheels of Ticketing - Desk Stories The Importance of Data Segregation Data segregation In ticketing systems, data segregation organises data into logical groups or categories to reduce ticket backlogs and resolution time and improve the overall customer
    • Inquiry Regarding Adding labels to Quick View Cards in Report

      Dear Zoho Support Team, I have created a report and designed it's Quick View and formatted the records as cards. However, I would like to include the field labels alongside the values for better clarity, as users may find it challenging to interpret the
    • Facing Issues? No typing—just record and share

      We get it—reporting a technical issue isn’t always easy. Explaining what went wrong over text can be time-consuming, and screenshots often miss the full context. That’s exactly why we want to spotlight a tool that’s been quietly waiting in your Zoho Recruit
    • Creation of Path and subpath

      In order to improve the structure of the website for better organization, I would like to consider that when publishing a page, it can be within a section and sub-section. For example, if I have an events option in the menu, I can put past events and
    • onDuty Request approval from API

      use case We have custom CRM modules and meeting devices where a user can add meeting details We are pushing these details to People using onDuty Request API Now what we want is If the onDuty request is pushed using API, it should be auto approved i-e
    • Move a mail to another inbox without being parto of it.

      I would like to move an email from my inbox to another team's inbox in, without being a member of that other team. The goal is to assign the customer's request to the colleagues who manage that inbox, so they can take over and handle it.
    • Zoho CRM CPQ NOT in criteria patern

      Hi, It would be great to have the logic-block of "NOT" in the criteria patern. Currently, only "AND" and "OR" are valid criteria when using the product configurator. Often, a "NOT" logic-block would greatly increase the usability of the CPQ. Example:
    • Filter by Portal User Reports no longer work

      I've had multiple reports that filter the data that shows based on the portal user - thisapp.portal.loginUserName(). They have worked fine for years but a few months ago they stopped working. Currently, no records appear in the report. Also, this is the
    • Quickly migrate attachments to Zoho CRM without having to restart the process multiple times

      Hello everyone, Customers often want to transfer all their data and attachments to Zoho CRM when they're switching CRMs (or moving from one Zoho CRM org to another). Admins use the built-in import tool to perform these migrations. There's a common source
    • Numeric Field Issue

      Hi We are trying to import deals but hitting a roadblock every time. If I create a single line field, the data imports fine for this field (it's a currency field in csv). I have found I can't sum this field though when trying to do a revenue report. When
    • Transfering Creator data to Books

      Hello, I am working on a new app that will have suppliers, products, customers, order, etc. When I will be finished, I will want the end result (an order of goods) to be transfered to Books for invoicing and accounting. I will also use the supplier order
    • Custom code ass to header and footer code doesn't appear

      I am trying to insert custom code into both the header and footer of my Zoho site. I edit the site "general settings" as demonstrated in the various articles, click save, but the code does not appear on my site. Is there something special I need to do
    • Geo-Powered Retail Intelligence with Zoho Analytics

      In today’s highly competitive retail landscape, data-driven decisions are no longer optional — they’re essential. While businesses collect vast volumes of data across regions, stores, and customer segments, the real value lies in how effectively this
    • In the Pivot table in the value section i want to the actual value instead of sum or count

      I am creating Early/late Check and check out in pivot report based on Zoho analytics I need the data to include: Employee Name Late Entry, Early Entry, Early Exit, Late Exit, First In, Last Out, and Total Hours.
    • Outgoing blocked again.

      Hi Dear, My outgoing mails are blocked again. I am just using it as normal business emails going in and out. Could you please help fix the problem? I am happy to support where I can do to make it work properly. Thank you very much. Aurora
    • Tip of the Week #54 – Automatically assign emails to your team members.

      Managing incoming emails can feel exhausting at times. But what if you could ensure that every email reaches the right team member — without lifting a finger? That’s where automatic email assignment comes in! With Zoho TeamInbox, you can easily set up
    • Keep your forms spam-free with CAPTCHA

      Is your online form getting loads of unwanted responses? Tired of spam ruining your valuable form data? CAPTCHA is the solution you are looking for. CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) is a simple yet effective
    • how to get the first word in string using deluge?

      let say I have string "David Beckham". how to get just "David" using deluge? I need to get the first word in string using deluge?
    • Access a field from incoming webhook Zoho Flow

      I would like to further process an incoming webhook in zoho flow. How can I access a field in the script / custom function. I tried this in many variations but not working: exfield=${webhookTrigger.payload.AnalyseErgebnis}; I would be very grateful if
    • Possible Bug: ZML Editor code in Panels not rendered successfully.

      I'm using Panels in my Zoho page because they allow clickable interactions like opening URLs or navigating to other pages. However, I'm facing two major issues: Persistent White Background: Despite multiple attempts, I’m unable to remove the default white
    • How to Find and Merge Duplicate records in Zoho CRM

      Hello Everyone,   Today, let's see how to find Duplicate records in your Zoho CRM account and Merge them.   Eliminating duplicate records in CRM seems to be a frequent issue for many businesses. Duplicate records can affect your productivity, increase manual work, and more importantly show incorrect data when it comes to reporting. Hence, it is crucial for businesses to have the ability to avoid creating duplicate records and the ability to merge duplicate records in CRM. As a first step, we need
    • Is Zoho Tables part of Zoho One

      Cant seem to add the app as part of my Zoho One Subscription?
    • Sending a Link to a Record in an Email template

      I recently introduced CRM Blueprints for the Deals module in my organization, and since our sales process involves several people from different departments, I created a few email templates to be used in the Email Notifications of some of the transitions, to let a user or group know that they need to take action or just be informed of a status change for that deal. Even though everything was working as expected, shortly after setting this up, some users came up to me asking if the notification email
    • Payroll in Saudi Arabia

      Zoho is a popular software platform that offers a wide range of business solutions, from customer relationship management to finance and accounting tools. However, one major drawback for businesses operating in Saudi Arabia is the lack of a payroll feature
    • How I can export emails from zoho crm ?

      Hello, I am looking for the workaround for exporting the sent e-mails. We use the Zoho crm free version (with upgrated storage) - and the e-mails are written/sent within/out of the crm feature. For our cases we only use 1) companies and 2) contacts -
    • Pre-loading related contact lookups to a subform

      Hello, I'm trying to create a module to track group meetings and field data for each group member. Subforms appear to be a good fit for this but I don't want to add each contact every time manually. Can anyone suggest a good solution for this scenario?
    • Fetching Comments From A Zoho Ticket Comment using Zoho Desk Api

      Hi I've been integrating Zoho Desk API into our product however, I'm unable to fetch any ticket comments when using your API. I get the following response => { "data": [] } The URL I'm hitting is https://desk.zoho.com/api/v1/tickets/ticketIdHERE/comments.
    • What are the formulas behind the system default dashboards?

      We want to know the exact formulas especially for the "time based dashboards". For example the "First Time Closure" logic for the "First Call Resolution" dashboard is not very clear. How does the system calculate that a ticket has been closed at the first time? Please elaborate with further details.
    • Grouping payments to match deposits

      Is there a way to group multiple invoice payments together so they match credit card batches and grouped deposits in the bank account? Basically, we are creating invoices for each of our transactions, and applying a payment to each of the invoices. Our payments are either credit cards or checks. We want to be able to group payments together so when our bank account reflects a credit card batch made up of many transactions, or the deposit we took to the bank that has multiple checks from different
    • How to create groups in Zoho People?

      I want to create groups and add users.
    • Deleted Blog Still Visible on Zoho Site

      I deleted the blog on the Zoho site and permanently removed it from the trash, but the article is still visible. Please make sure it does not appear. The URL is below https://seeds.tech-manage.co.jp/blogs/post/WL-04550
    • Data Import validations

      Hi, I currently have a CSV file download from a 3rd party SFTP server prior to performing the data transform. When we don't have any transactional data, a file is still uploaded by the 3rd party to the server, but it is blank. This causes the transform
    • Is Setting Up Sub Domain for Email Sends Good Idea?

      Hi there, our team just bought a dedicated IP for our email sends. We send more than 100k emails/month. Because we face deliverability issues and also because of the mass sends, we decided to get a dedicated IP. My question is, should we set up subdomains
    • Abandoned Cart Recovery doesnt work on Woocommerce

      Hi, Does someone have implemented ACR with Woo successfully? My connection seems to be established but no user entered the workflow since I'm running the integration. I also faced problems in reinstalling the plugin on my wordpress. I simply cant uninstall.
    • Vault extension for Chrome rarely works anymore in Brave browser

      Hello, Until about a year ago the Vault extension for Chrome worked very reliably in the Brave browser. Since then, though, the extension fails to open, more often than not. Is there a known fix for this? I love Vault - it is, by far, the best password
    • Discussion : How are you sharing your Zoho Analytics Dashboards/Reports?

      I have all of my companies data in Zoho Analytics and now want to use it to prepare regular reporting for my SLT. They currently produce a Word document with screen shots of various reports… Analytics own dashboard engine is not great and doesn't fit
    • Collaborate without compromise, with Ticket Sharing.

      We often hear that the ability to move tickets is a big benefit. That kind of flexibility is great to have when your tickets require expertise across departments. But there's often a price to pay: Moving tickets across departments could result in a (well-intentioned) battle for access. When tickets move between departments while agents are working on them, chaos ensues.   To put an end to all these worries, Zoho Desk brings out a new ticket action: simply share. With ticket sharing, everyone gets
    • 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,
    • Next Page