<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joseph Petty</title>
    <description>The latest articles on DEV Community by Joseph Petty (@joseph_appsmith).</description>
    <link>https://dev.to/joseph_appsmith</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1182310%2F263a8872-d876-488d-ad20-084ad0b6ca26.jpeg</url>
      <title>DEV Community: Joseph Petty</title>
      <link>https://dev.to/joseph_appsmith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joseph_appsmith"/>
    <language>en</language>
    <item>
      <title>OpenAI Assistants with Structured Outputs</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Fri, 03 Jan 2025 14:13:20 +0000</pubDate>
      <link>https://dev.to/appsmith/openai-assistants-with-structured-outputs-3h2l</link>
      <guid>https://dev.to/appsmith/openai-assistants-with-structured-outputs-3h2l</guid>
      <description>&lt;p&gt;OpenAI recently added support to their API for structured outputs, which allow you to define the response format using JSON Schema. Prior to this, the JSON response mode was able to reply with JSON, but there was no way to enforce a specific structure, define enum values, and specify required or optional fields. But with Structured Outputs, you can define every detail about the response, to ensure the data is ready to be passed on to your database or workflow. &lt;/p&gt;

&lt;p&gt;In this guide, I'll be using OpenAI's Structured Outputs to analyze customer reviews for a hotel chain. The reviews only contain the rating (1-5), and the review text. The Structured Output feature will be used to add new datapoints for sentiment (positive, neutral, negative), offensiveContent (true/false), and tags (cleanliness, service, staff, etc). &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This guide will cover:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating an OpenAI API key and saving it to an Appsmith datasource&lt;/li&gt;
&lt;li&gt;Using the Chat /completions API&lt;/li&gt;
&lt;li&gt;Building a UI to select and send reviews to the assistant&lt;/li&gt;
&lt;li&gt;Defining a JSON Schema for the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Lbt_eIdzHf8" rel="noopener noreferrer"&gt;YOUTUBE: OpenAI Assistants with Structured Outputs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.appsmith.com/content/guide/openai-assistants-structured-outputs" rel="noopener noreferrer"&gt;Written tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openai</category>
      <category>ai</category>
      <category>appsmith</category>
    </item>
    <item>
      <title>Enterprises Are Embracing Low-Code 2024, and Fullstack Developers Have an Advantage</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Mon, 13 May 2024 15:18:07 +0000</pubDate>
      <link>https://dev.to/appsmith/enterprises-are-embracing-low-code-2024-and-fullstack-developers-have-an-advantage-fm4</link>
      <guid>https://dev.to/appsmith/enterprises-are-embracing-low-code-2024-and-fullstack-developers-have-an-advantage-fm4</guid>
      <description>&lt;h2&gt;
  
  
  Low-Code: New Name, Same Game?
&lt;/h2&gt;

&lt;p&gt;The term low-code is fairly new, but the idea has been around for decades:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved efficiency through abstraction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previous marketing trends used terms like visual programming language (VPL), rapid application development (RAD), GUI builders, etc. But most of these older platforms required installed software, both for the builder and client (end user), like MicroSoft Access, Borland Delphi, and FileMaker Pro.&lt;/p&gt;

&lt;p&gt;Then, in the 2000's, platforms like MS SharePoint, Zoho Creator and Mendix started to offer web based builders and clients. This shift increased accessibility and enabled more use cases, allowing businesses to build their own customer facing portals, and dashboards that the team could access from anywhere. Everything was perfect, and the devs had nothing to complain about! That is, until they started thinking about self-hosting, A/B testing, continuous delivery, multiple environments, SSO, version control... and why they ever gave up the fullstack approach.&lt;/p&gt;

&lt;p&gt;But in recent years, platforms like Appsmith have begun addressing these concerns with a more comprehensive solution. With features like version control with Git, auto-user provisioning with SCIM, and Granular Access Control, Appsmith brings that improved efficiency to the entire platform and software development life-cycle, instead of just in the &lt;em&gt;app-building&lt;/em&gt; process.&lt;/p&gt;

&lt;p&gt;THIS is the key factor that enables enterprises to adopt modern low-code solutions, because it means they can operate and maintain them at scale. Low-code is no longer just a tool for building MVPs and side-projects; it's ready for prime-time with the largest enterprises in the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Driving the Change?
&lt;/h2&gt;

&lt;p&gt;The fact that low-code tools are finally ready to support enterprise use cases is only part of it. The real pressure that's driving the shift to low-code is more financial in nature. In 2023 alone, 191,000 workers were laid off in just the US. Amazon, Alphabet, Microsoft and Meta lead the reductions, each with over 10k workers let go. Businesses have to do more with less, and that means less people &lt;em&gt;and less software expenses&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There has always been financial pressure for enterprises to choose the most cost-effective solution, but until recently, web-based low-code solutions lacked the necessary enterprise features, security compliance, SLAs, and other requirements. Now, enterprises have a viable alternative that saves time and money, while maintaining security, stability and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easier access = more use cases, but not more devs
&lt;/h2&gt;

&lt;p&gt;Appsmith and other low-code tools enable teams to quickly build apps for any internal process. This means that smaller use cases can be addressed that never would have justified the investment of a fullstack application. Now any team within the company can spin up their own app for HR, Customer Support, PayRoll, etc, instead of only one team trying to serve every department and having to prioritize a backlog of requests.&lt;/p&gt;

&lt;p&gt;More use cases means more devs are needed. And while Appsmith makes it easy for anyone to build their first app, what enterprises really need is experienced developers to properly design and build enterprise-grade apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Low-Code for Fullstack and Backend Developers
&lt;/h2&gt;

&lt;p&gt;Appsmith is low-code where it makes sense, and full-code when you need it. The UI is drag-n-drop, and requires no frontend experience. But when it comes to connecting to datasources, this is a developer's tool. There's no abstraction getting between you and the data. The API builder is similar to Postman, and the query builder lets you write SQL and interact directly with the database. You can also write JavaScript anywhere to add logic to dynamically control the UI and create workflows. And with custom widgets, you can use any library or framework to build other UI components in addition to our 45+ prebuilt widgets.&lt;/p&gt;

&lt;p&gt;This approach means the platform is familiar to fullstack or backend developers, but sometimes harder for non-developers or no-code devs to pick up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fullstack Developer's Advantage
&lt;/h2&gt;

&lt;p&gt;Appsmith can &lt;a href="https://www.appsmith.com/integration"&gt;connect&lt;/a&gt; to just about any API or database, and that's one of the areas our customers tend to need help. It's not about learning Appsmith, but about having expertise in OAuth2, JavaScript, SQL, &lt;a href="https://docs.appsmith.com/getting-started/setup"&gt;self-hosting&lt;/a&gt;, and experience working with stakeholders to gather requirement and properly design the backend.&lt;/p&gt;

&lt;p&gt;Anyone can use low-code tools to throw together a basic CRUD app, but it takes an experience developer to build, deploy and manage an enterprise-grade solution with performant queries, granular permissions and other best practices in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Fullstack
&lt;/h2&gt;

&lt;p&gt;With so many enterprises shifting to low-code, now is the perfect time for fullstack developers to start adding low-code skills to their toolkit, and resumes! Appsmith is open-source and can be self-hosted for free, making it the perfect choice for the frontend in a modern fullstack. Throw in an open-source backend like Supabase, Baserow, or Postgres, and you've got a modern, easy to deploy and maintain fullstack. Enterprise customers are making the switch to low-code, and they need your fullstack experience. It's time for traditional fullstack developers to embrace low-code and the new fullstack!&lt;/p&gt;

&lt;h2&gt;
  
  
  Freelancing and Building an Online Presence
&lt;/h2&gt;

&lt;p&gt;Whether working in a full-time developer role for one company, or as a solo freelancer, all fullstack devs can benefit from adding low-code tools to their stack. But fullstack freelancers in particular will gain even more of an advantage.&lt;/p&gt;

&lt;p&gt;Low-code tools are generally much easier to use, and most users can build a simple CRUD app with no problem. But for those more advanced use cases, fullstack experience goes a long way. When it comes time to build a &lt;a href="https://youtu.be/yfPn4XwJ7pc"&gt;custom widget&lt;/a&gt;, transform data for a chart, or integrate with an OAuth2 API, traditional devs will excel where no-code devs and non-developers would struggle.&lt;/p&gt;

&lt;p&gt;If you're interested freelancing with low-code tools, one of the most important things you can do is to start building an online presence in the low-code space. This means asking and answering questions on forums, starting a blog and posting tutorials, and building an online portfolio. Get yourself out there in the community and make a name for yourself as someone who understands the product and wants to help others. This could apply to a specific tool like Appsmith or Supabase, or in a certain domain of tech, like JavaScript or Postgres forums. &lt;/p&gt;

&lt;p&gt;It takes time to build, but a solid online presence can drive tons of leads to your UpWork or Fiverr profile, personal website, or wherever else you want to direct them. Additionally, your tutorial or community profile on a forum can be included in proposals, as a way to build confidence in potential clients and show them that you are invested in building quality solutions with that particular product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advertising on the Appsmith Community Portal
&lt;/h2&gt;

&lt;p&gt;Appsmith is a BYOD (Bring your own datasource) platform, so building an Appsmith app often involves other skills like SQL, JavaScript, API integrations, etc. Therefore, we've designed our community directory to allow anyone to advertise these services, in addition to Appsmith development. In other words, you don't have to be an Appsmith expert to make a profile and use the community portal to find work! There are tags for other skills you can add to your profile, like JavaScript, SQL, Google Sheets, etc. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's how you can get started:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a profile on the &lt;a href="https://community.appsmith.com/directory"&gt;community portal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Ensure your profile is 100% complete&lt;/li&gt;
&lt;li&gt;  Include a link or email for the &lt;strong&gt;Contact Me&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;  Request to have your account verified (ask Appsmith staff on &lt;a href="https://discord.com/invite/rBTTVJp"&gt;Discord&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Low-code tools have advanced from being installed programs that are locked to a desktop, to web-based, self-hostable platforms with enterprise features like SSO, multiple environments, version control with git, and role based access control. And now the advantages of low-code are finally accessible to large enterprises that were previously blocked by security and regulatory compliance. This shift is creating increased demand for low-code developers, and fullstack developers have a clear advantage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.appsmith.com/content/blog/getting-started-low-code-freelancer-5-tips-kickstart-your-career-2024"&gt;Finding Work As A Low-Code Freelancer&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Mermaid.js Gantt Chart in a FileMaker Web Viewer</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Mon, 08 Apr 2024 17:54:02 +0000</pubDate>
      <link>https://dev.to/appsmith/building-a-mermaidjs-gantt-chart-in-a-filemaker-web-viewer-on6</link>
      <guid>https://dev.to/appsmith/building-a-mermaidjs-gantt-chart-in-a-filemaker-web-viewer-on6</guid>
      <description>&lt;p&gt;I’ve used a lot of low-code tools over the years, and one thing I’ve always enjoyed is pushing the limits of each platform and building things that aren’t supported out of the box. The first tool I really dove into was Claris FileMaker Pro. At the time (2010ish), I had no programming experience, so I really had no idea what to do with a web viewer in FileMaker (iframes in Appsmith), other than display a site from some external url. It didn’t seem all that useful to me. &lt;/p&gt;

&lt;p&gt;Fast forward to today- I’ve spent the last few years pushing the limits of Appsmith, using iframes and &lt;a href="https://www.youtube.com/watch?v=2YXveLr6ANk"&gt;custom widget&lt;/a&gt; with &lt;a href="https://docs.appsmith.com/core-concepts/writing-code/ext-libraries"&gt;external libraries&lt;/a&gt; to create all sorts of new UI components and features. I now understand how powerful an iframe can be in a low-code tool. It’s an escape hatch for when you hit platform limits. It’s like punching a hole in the ceiling, making the sky the limit. &lt;/p&gt;

&lt;p&gt;I’ve been out of FileMaker development for years, but recently I started thinking about all the cool stuff I could have done back then if I had known a little more about JavaScript and using libraries in an iframe. So I’ve decided to revisit my first ‘go-to’ platform, and rebuild some of the &lt;a href="https://community.appsmith.com/user/3/templates"&gt;recent experiments&lt;/a&gt; I’ve been doing in Appsmith. &lt;/p&gt;

&lt;p&gt;Today, I’ll be working with the Mermaid JS library to generate flow charts from records stored in FileMaker. This post was inspired by an Appsmith community &lt;a href="https://community.appsmith.com/template/mermaid-workflows-and-graphs"&gt;template&lt;/a&gt; from Paul Chambless. Thanks Paul! &lt;/p&gt;

&lt;h2&gt;
  
  
  Mermaid.JS Intro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mermaid.js.org/"&gt;Mermaid JS&lt;/a&gt; is a powerful JavaScript library that allows developers to create complex diagrams and visualizations using simple text and code syntax. It’s a lot like markdown, but for charts instead of plain text. &lt;/p&gt;

&lt;p&gt;For instance, just a few lines of text can be used to create a pie chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pie title NETFLIX
         "Time spent looking for movie" : 90
         "Time spent watching it" : 10

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7e3nparu4l7qyqf6n2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7e3nparu4l7qyqf6n2b.png" alt="Image description" width="686" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works by placing the Mermaid code inside a div, and giving it the class of mermaid. The Mermaid library parses the doc and replaces all the mermaid divs with the rendered chart or graph, based on the text content of the div. Here's a full HTML doc, showing how to import the library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Mermaid Graph&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;startOnLoad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Mermaid diagram container --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mermaid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
sequenceDiagram
    participant Research
    participant Design
    participant Development
    participant Testing
    participant Deployment
    Research-&amp;gt;&amp;gt;Design: Completed
    Design-&amp;gt;&amp;gt;Development: In Progress
    Development-&amp;gt;&amp;gt;Testing: Pending
    Testing-&amp;gt;&amp;gt;Deployment: Pending
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…which renders as&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funy03qhlukx94acq56a9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funy03qhlukx94acq56a9.png" alt="Image description" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Mermaid in FileMaker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a template for the web viewer
&lt;/h3&gt;

&lt;p&gt;First, create a template for the web viewer and insert a MERMAID_CODE placeholder for where the Mermaid code would go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Mermaid Graph&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;startOnLoad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Mermaid diagram container --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mermaid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
MERMAID_CODE
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then save this to a field in a new table. For mine, I used &lt;code&gt;webviewer::html&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Set up web viewer
&lt;/h3&gt;

&lt;p&gt;Next, add a code field to the same table, and add it to a layout, along with a web viewer. &lt;/p&gt;

&lt;p&gt;Set the web viwer contents to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Substitute ( html ; “MERMAID_CODE” ; code )

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Load in a Mermaid Example
&lt;/h3&gt;

&lt;p&gt;Now just paste any example from the Mermaid docs into the code field, and you should have a working chart or graph. This is hard-coded though. We want to insert data from FileMaker! That’s going to require some calculations and/or scripting. But before we shift gears, there’s one more thing we can do while we’re here. &lt;/p&gt;

&lt;p&gt;You may want to add some custom styling, or even use other JavaScript libraries in the same web viewer. To make this easier, I suggest adding two more fields for css and javascript. Then update the template and the web viewer accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Mermaid Graph&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;startOnLoad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;CSS_CODE&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;JS_CODE&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Mermaid diagram container --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mermaid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
MERMAID_CODE
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this for the calculation in the web viewer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Substitute ( html ; 

  ["JS_CODE" ; js ];  

  ["CSS_CODE" ; css ] ;

  ["MERMAID_CODE" ; mermaid ]

)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also want to add a Tab Control with Panels to edit each field. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uaxqeykthi6bpckmfzi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uaxqeykthi6bpckmfzi.png" alt="Image description" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Text for Mermaid Charts
&lt;/h2&gt;

&lt;p&gt;Ok, now that the basics are working, on to the fun part! Generating Mermaid charts dynamically from FileMaker data.&lt;/p&gt;

&lt;p&gt;I have a Tasks table with the following data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cdmw1mpdwdq12aux96a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cdmw1mpdwdq12aux96a.png" alt="Image description" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I need to turn it into this format for a Gantt chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gantt
title A Gantt Diagram
dateFormat  YYYY-MM-DD
Project Task 1: Task 1, 2024-04-04, 2024-04-07
Project Task 2: Task 2, 2024-04-06, 2024-04-09
Project Task 3: Task 3, 2024-04-08, 2024-04-11
Project Task 4: Task 4, 2024-04-10, 2024-04-13
Project Task 5: Task 5, 2024-04-12, 2024-04-15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Years ago I would have approached this with a script, but now we have the WHILE function in FileMaker. No looping scripts needed! &lt;/p&gt;

&lt;p&gt;First, I used ExecuteSQL to get the data as comma separated values. But one of my column names is an &lt;a href="https://community.appsmith.com/content/blog/sql-reserved-words"&gt;SQL reserved word&lt;/a&gt;, so I had to use escape quotes. Then I used SUBSTITUTE to break each row into a new list item to iterate through. From there, a used a WHILE loop to build each task entry, then return the final list, along with the extra header info needed for this chart type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let([
    ganttHeader = "gantt" &amp;amp; ¶ &amp;amp;
    "title A Gantt Diagram"  &amp;amp; ¶ &amp;amp;
    "dateFormat  YYYY-MM-DD";

    data = ExecuteSQL("SELECT name, start, \"end\", id FROM Tasks"; ""; "¶");
    rows = Substitute(data; "¶"; ¶);
    maxIndex = ValueCount(rows)
];
    ganttHeader &amp;amp; ¶ &amp;amp; 
    While([
        index = 1;
        ganttBody = ""
    ];
        index &amp;lt;= maxIndex;
        [
            row = GetValue(rows; index);
            fields = Substitute(row; ","; ¶);
            taskName = GetValue(fields; 1);
            startDate = GetValue(fields; 2);
            endDate = GetValue(fields; 3);
            id = GetValue(fields; 4);

            // Construct the Gantt chart entry for this task
            ganttEntry = taskName &amp;amp; ": " &amp;amp; id &amp;amp; ", " &amp;amp; startDate &amp;amp; ", " &amp;amp; endDate;

            // Append this task's entry to the ganttBody
            ganttBody = ganttBody &amp;amp; ganttEntry &amp;amp; ¶;
            index = index + 1
        ];
Substitute(ganttBody; "¶"; ¶)    )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this in a calculation field with the &lt;em&gt;‘do not store result’&lt;/em&gt; option will enable realtime charts based on your data! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwepnpfpawe4hz440lsyl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwepnpfpawe4hz440lsyl.gif" alt="Image description" width="1342" height="883"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a fun, first-try at using a web viewer in FileMaker for something besides displaying an external website. There are a ton of other use cases and JavaScript libraries that could be used to extend FileMaker Pro, Appsmith, or any other low-code platform that supports iframes or custom widgets. &lt;/p&gt;

&lt;p&gt;I hope this helps other get started with 'punching holes in the ceiling' of platform limitations! Got an idea for a new integration? Drop a comment below. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related Post&lt;/strong&gt;: &lt;a href="https://community.appsmith.com/content/blog/filemaker-api-connector-free-and-open-source-starter-solution-integrating-filemaker"&gt;https://community.appsmith.com/content/blog/filemaker-api-connector-free-and-open-source-starter-solution-integrating-filemaker&lt;/a&gt;&lt;/p&gt;

</description>
      <category>filemaker</category>
      <category>javascript</category>
      <category>lowcode</category>
      <category>sql</category>
    </item>
    <item>
      <title>FileMaker API Connector: A Free and Open-Source Starter Solution for Integrating FileMaker with Any API Or Database</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Tue, 02 Apr 2024 22:00:00 +0000</pubDate>
      <link>https://dev.to/appsmith/filemaker-api-connector-a-free-and-open-source-starter-solution-for-integrating-filemaker-with-any-api-or-database-1j27</link>
      <guid>https://dev.to/appsmith/filemaker-api-connector-a-free-and-open-source-starter-solution-for-integrating-filemaker-with-any-api-or-database-1j27</guid>
      <description>&lt;p&gt;Hey, I'm Joseph, an engineer at Appsmith, and a long-time FileMaker Pro consultant and developer. I freelanced in FileMaker Pro for years, integrating APIs like Shopify, BigCommerce, eBay and other services, using the insert from URL script step, curl requests, and roughly a terabyte of &lt;code&gt;\"escaped quotes\"&lt;/code&gt; 😖&lt;/p&gt;

&lt;p&gt;FileMaker is a powerful low-code platform that can build some pretty amazing apps, but the developer experience isn’t always as… let’s just say — modern. And while curl requests still have their uses, these days, I’d much rather use a Postman-like interface for making API calls. &lt;strong&gt;So I built one!&lt;/strong&gt; And I wanted to share it with the FileMaker community.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feu5j732r2o00bnzq45cv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feu5j732r2o00bnzq45cv.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.appsmith.com/template/filemaker-api-connector"&gt;This app&lt;/a&gt;, built on Appsmith, provides a starting point for connecting your FileMaker data to almost any API or Database using one of Appsmith’s many &lt;a href="https://www.appsmith.com/integration?utm_source=reddit&amp;amp;utm_medium=filemaker-reddit&amp;amp;utm_content=appsmith_apps&amp;amp;utm_campaign=devrel&amp;amp;utm_term=integration"&gt;integrations&lt;/a&gt;, and a Postman-like API builder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs81masgmo9pjvp35b61o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs81masgmo9pjvp35b61o.png" alt="Image description" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhlm1jakpdyeath789ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhlm1jakpdyeath789ey.png" alt="Image description" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;The app handles the FileMaker login flow and query building, using a UI to select fields and enter search terms without coding—just like a Find Request in FileMaker. It generates the actual JSON query object for you and runs the API request, returning any matching records.&lt;/p&gt;

&lt;p&gt;To get started, click the &lt;a href="https://app.appsmith.com/app/filemaker-api-connector/fmp-to-api-6304e44ab189ad45f609d8bb?utm_source=reddit&amp;amp;utm_medium=filemaker-reddit&amp;amp;utm_content=appsmith_apps&amp;amp;utm_campaign=devrel&amp;amp;utm_term=filemaker-appsmith-app"&gt;Fork App&lt;/a&gt; button in the top right to copy the app to your Appsmith account. Then, follow the instructions in the app to connect to your FileMaker server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftb1ozu0vift3twdh7p0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftb1ozu0vift3twdh7p0k.png" alt="Image description" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FileMaker API Connection Settings
&lt;/h2&gt;

&lt;p&gt;Click the &lt;strong&gt;Test Connection&lt;/strong&gt; button to verify if the API is working, and then close the setup window.&lt;/p&gt;

&lt;p&gt;Enter the layout name you want to query, and the app will pull in the table name, field names, and total record count. This populates the Select widgets in the query builder so you can easily build complex &lt;code&gt;AND&lt;/code&gt;/&lt;code&gt;OR&lt;/code&gt; queries with multiple conditions.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;FIND&lt;/strong&gt; to run the query and the table should populate with the first 100 records from your FileMaker database. This query builder uses Appsmith's &lt;a href="https://docs.appsmith.com/reference/widgets/json-form?utm_source=reddit&amp;amp;utm_medium=filemaker-reddit&amp;amp;utm_content=appsmith_apps&amp;amp;utm_campaign=devrel&amp;amp;utm_term=docs"&gt;JSON Form widget&lt;/a&gt;, which dynamically generates a form from a JSON object.&lt;/p&gt;

&lt;p&gt;Next, try entering a few search terms using the query builder, and set a &lt;strong&gt;Query Type&lt;/strong&gt;: &lt;code&gt;AND&lt;/code&gt; or &lt;code&gt;OR&lt;/code&gt;. See how the query-body preview updates and the JSON structure changes? Awesome! Now let's check out the API requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvadef84k03y3pdvr990.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvadef84k03y3pdvr990.png" alt="Image description" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FileMaker API Query Type
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The FileMaker API uses a &lt;code&gt;GET&lt;/code&gt; method to retrieve records from a layout if no specific filter is used. However, to perform a find request, a &lt;code&gt;POST&lt;/code&gt; method is used to send the query conditions in the POST body.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The search works the same as FileMaker's native find requests, using the same operators for wildcards &lt;code&gt;*&lt;/code&gt;, exact matches &lt;code&gt;==&lt;/code&gt;, and others.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;AND&lt;/code&gt; &lt;strong&gt;requests group the conditions as multiple properties of the same object:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "query": [
    {
      "address_state": "FL",
      "first_name": "J*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OR&lt;/code&gt; &lt;strong&gt;requests separate each condition into a separate object:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "query": [
    {
      "address_state": "FL"
    },
    {
      "first_name": "J*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;Feel free to skip to the next section if your table has &amp;lt;=100 records. Still here? Ok, well it sounds like you might need to paginate your data. &lt;strong&gt;But do you?&lt;/strong&gt; 🤨&lt;/p&gt;

&lt;p&gt;If possible, try to request only the records needed client-side and limit the results to less than 100 records, the limit per request for the FileMaker API. If you really need more than 100 records pulled, check out this &lt;a href="https://docs.appsmith.com/core-concepts/data-access-and-binding/displaying-data-read/display-data-tables#pagination"&gt;guide&lt;/a&gt; on pagination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Low-code: Integrate with another database or API
&lt;/h2&gt;

&lt;p&gt;There's a lot you can do without coding in Appsmith, but you can do even more with JavaScript, like controlling widgets’ behaviors and appearances, transforming data, or chaining together multiple actions. This app was built using a few JavaScript nuggets to make the query builder, but it can easily be extended to send data to another API or database without additional coding.&lt;/p&gt;

&lt;p&gt;Just add a new column to the table widget and set the type to Button. Then add a new API or database query to send data from the current row to another system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4242yebu7jp0dw9yftl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4242yebu7jp0dw9yftl.png" alt="Image description" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the query body with JavaScript
&lt;/h2&gt;

&lt;p&gt;The JSONForm widget supports Array and Object type fields, and allows the user to add additional objects—sets of fields and values—to an array. In this case, you are adding new query objects with inputs for the &lt;code&gt;field_name&lt;/code&gt; and &lt;code&gt;search_term&lt;/code&gt;. The data can be accessed inside the JSONForm widget by referencing &lt;code&gt;JSONForm1.formData&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "query": [
    {
      "field_name": "address_state",
      "search_term": "FL"
    },
    {
      "field_name": "first_name",
      "search_term": "J*"
    }
  ],
  "query_type": "AND"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, this data is transformed using a &lt;code&gt;map()&lt;/code&gt; function, or &lt;code&gt;forEach()&lt;/code&gt; function, depending on the &lt;strong&gt;query_type&lt;/strong&gt;—&lt;code&gt;AND&lt;/code&gt; or &lt;code&gt;OR&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!JSONForm1.formData?.query) {
  return ''
}
let queryBody = {
  query: [{}]
};
let conditions = JSONForm1.formData.query;
let queryType = JSONForm1.formData.query_type;
if (queryType == 'OR') {
  let body = conditions.map(c =&amp;gt; ({[c.field_name]: c.search_term}));
  queryBody['query'] = body;
} else {
  conditions.forEach(c =&amp;gt; queryBody['query'][0][c.field_name] = c.search_term)
};
return queryBody
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server credentials and security
&lt;/h2&gt;

&lt;p&gt;For easy setup and demo, this public Appsmith app was built using a client-side form to input the FileMaker API credentials as an app user. Appsmith also offer a secure datasource feature that saves the credentials on your Appsmith server as an admin, without exposing them to the user. Check out our &lt;a href="https://docs.appsmith.com/core-concepts/connecting-to-data-sources/authentication#create-authenticated-api"&gt;Authenticated API&lt;/a&gt; docs for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;I started this app as a fun experiment to learn the FileMaker API and query structure, but it quickly evolved into the perfect starting point to connect FileMaker to any API or database. Hope this helps you get started on your own integrations!&lt;/p&gt;

&lt;p&gt;I would love to hear back from you on your experience using the app, or if you would like to collaborate on adding additional features. I may even open-source this app as its own project if others are interested in contributing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update: April 2024
&lt;/h2&gt;

&lt;p&gt;I got my start with FileMaker Pro in 2010 while working at a national laboratory that used it for data collection. The database needed some updates so I taught myself, and I ended up becoming the main dev for any FMP work at the lab. That lead to some side work, and more work, and then in 2016 I left the lab to start my own company and freelance full time. &lt;/p&gt;

&lt;p&gt;After a few years of FMP, I switched to Google AppSheet for about 4 years, then found Appsmith in 2020 and made it my main tool for freelance work. I joined the Appsmith team about 1.5 years later as a senior developer advocate, and now I lead our freelancer program. It's been an amazing journey, and I couldn't have done it without the communities around each one of the platforms I used along the way. So now I want to help other low-code freelancers in their journeys by building our developer community with freelancers in mind. &lt;/p&gt;

&lt;p&gt;If you're a freelancer in Appsmith, AppSheet, or FileMaker Pro, or any other low-code platform, I'd love to hear from you. And if you want to start freelancing but don't know where to start, feel free to reach out on Discord (joseph_appsmith). &lt;/p&gt;

</description>
      <category>filemaker</category>
      <category>api</category>
      <category>appsmith</category>
      <category>developer</category>
    </item>
    <item>
      <title>Understanding 'Single' vs "Double" Quotation Marks in PostgreSQL</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Fri, 19 Jan 2024 08:00:00 +0000</pubDate>
      <link>https://dev.to/appsmith/understanding-single-vs-double-quotation-marks-in-postgresql-dk0</link>
      <guid>https://dev.to/appsmith/understanding-single-vs-double-quotation-marks-in-postgresql-dk0</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Single Quotes: Representing Textual Values&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In PostgreSQL, single quotation marks are used to indicate textual values, often referred to as string literals. These string literals are essential for expressing information like names, descriptions, or any other form of textual data within SQL statements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Single Quotes for String Values
&lt;/h3&gt;

&lt;p&gt;When inserting data into a database, the string should be encased in single quotes. For instance, if you're adding a new entry to a &lt;strong&gt;products&lt;/strong&gt; table, and you want to specify the product name as "Sparkling Water," you would use single quotes as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sparkling Water'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By enclosing the product name in single quotes, you're indicating that "Sparkling Water" is a string literal, allowing PostgreSQL to interpret and store it correctly. Notice how there are no quotes on the price, because the data is a number, not a string. &lt;/p&gt;

&lt;h3&gt;
  
  
  Escaping Single Quotes
&lt;/h3&gt;

&lt;p&gt;Suppose you need to include an actual single quote within your string. In that case, you can't directly use a single quote, as it would prematurely terminate the string. To handle this situation, you use two consecutive single quotes to represent a single quote character within the string. For example, if you want to insert the string "It's a sunny day," you would do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;weather_reports&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'It&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s a sunny day'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using two consecutive single quotes (&lt;strong&gt;''&lt;/strong&gt;), you're escaping the single quote character and ensuring it's treated as part of the string value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Double Quotes: Identifying Delimited Identifiers
&lt;/h2&gt;

&lt;p&gt;Unlike single quotes, which deal with string values, double quotes are utilized to mark delimited identifiers. These identifiers are names of database objects such as tables, columns, or even roles. The use of double quotes helps distinguish these identifiers and allows for special characters or case sensitivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quoting for Delimited Identifiers
&lt;/h3&gt;

&lt;p&gt;Suppose you're creating a table named &lt;strong&gt;Employee Records&lt;/strong&gt;. Since this name contains a space, which is not a standard character for identifiers, you would use double quotes to define it as a delimited identifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Employee Records"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;employee_name&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By enclosing the table name in double quotes, you're indicating that it's a delimited identifier, allowing PostgreSQL to treat the space as part of the name. &lt;/p&gt;

&lt;h3&gt;
  
  
  Case Sensitivity with Double Quotes
&lt;/h3&gt;

&lt;p&gt;Double quotes introduce case sensitivity to identifiers. For instance, if you create a column named "TotalSales" with double quotes, you must always reference it with the same case and double quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"TotalSales"&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sales_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the double quotes, PostgreSQL would interpret the column name in a case-insensitive manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating a New Table
&lt;/h3&gt;

&lt;p&gt;Imagine you're creating a new table to store customer reviews. Let's call it "Product Reviews." To ensure the table name is recognized as a single identifier and that the casing is preserved, you can use double quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Product Reviews"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;review_id&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;review_text&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, the double quotes are utilized to create a delimited identifier for the table name "Product Reviews," allowing the use of spaces and upper casing within the name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Querying Data with Delimited Identifiers
&lt;/h3&gt;

&lt;p&gt;Suppose you want to retrieve reviews from the "Product Reviews" table where the product name is "Sparkling Water". Since the table name contains capitalization and spaces, you would need to use double quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;review_text&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"Product Reviews"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sparkling Water'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the double quotes ensure that PostgreSQL correctly interprets the capitalized table name "Product Reviews.", and the single quotes are used to encase the string used as a search term in the WHERE clause. &lt;/p&gt;

&lt;h3&gt;
  
  
  Using Single Quotes for String Values
&lt;/h3&gt;

&lt;p&gt;Let's insert a new review into the "Product Reviews" table. The review text is "Great product, highly recommended!":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="nv"&gt;"Product Reviews"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Great product, highly recommended!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the single quotes are used to enclose the review text, indicating that it's a string value to be inserted into the table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escaping Single Quotes in String Values
&lt;/h3&gt;

&lt;p&gt;Suppose you receive a review with an apostrophe within the text. For example, "It's the best choice." To insert this review accurately, you need to escape the apostrophe using two consecutive single quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="nv"&gt;"Product Reviews"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'It&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s the best choice.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doubling the single quotes (''), you're correctly inserting the review without prematurely ending the string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Understanding the use of single and double quotation marks in PostgreSQL is critical for effective database manipulation. Single quotes represent textual values, while double quotes denote delimited identifiers, such as table and column names.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
      <category>programming</category>
      <category>database</category>
    </item>
    <item>
      <title>Getting Started As a Low-Code Freelancer: 5 Tips to Kickstart Your Career in 2024</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Sat, 16 Dec 2023 15:25:21 +0000</pubDate>
      <link>https://dev.to/appsmith/getting-started-as-a-low-code-freelancer-5-tips-to-kickstart-your-career-in-2024-2k1f</link>
      <guid>https://dev.to/appsmith/getting-started-as-a-low-code-freelancer-5-tips-to-kickstart-your-career-in-2024-2k1f</guid>
      <description>&lt;p&gt;With tons of new no-code/low-code platforms, a wide range of new AI tools, and massive changes in freelancing sites, 2023 has led to significant changes in the freelancer landscape. Freelancing in 2024 will be completely different game, which will come with new challenges, and even more new tools to learn to help solve them. &lt;/p&gt;

&lt;p&gt;To be successful in this market as a freelancer, you must adapt and learn to take advantage of change instead of be disrupted by it. But despite all the change, there are some tried and true freelancing techniques that still apply. After working full-time as a freelancer in the no-code/low-code space for almost a decade, and mentoring several other freelancers along the way, I've seen what works and what doesn't, what used to work, and what has changed. Below are my top 5 tips for freelancing in this new landscape. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tip #1 - Create Your Own Niche
&lt;/h2&gt;

&lt;p&gt;Combine a personal skill, hobby or other area of expertise with a specific platform or language. You might not be the best freelancer available for a certain platform, but when combined with that extra skill or hobby, you could quickly become one of the top choices for clients who want that specialty. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;: Healthcare + Bubble.io, Finance + Airtable, ecommerce APIs + Appsmith, Construction/Manufacturing + AppSheet, etc&lt;/p&gt;

&lt;p&gt;This creates a combo of search terms with much fewer results, allowing your profile and content to rise to the top when you specialize in both. It will also help close the deal when the client knows you understand the platform AND the processes and data structure specific to their use case. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tip #2 - Learn in Public
&lt;/h2&gt;

&lt;p&gt;Document and share your learning journey. Now that you've learned &lt;em&gt;How to do X in Y Platform&lt;/em&gt;, go write a post on their community forums! This is something I have done from the very beginning of my freelancer career. I figured, why not make my notes public and save others the trouble I went through to learn it. &lt;/p&gt;

&lt;p&gt;Also be sure to fill out your profile on these forums, and add links to your blog and freelancer profiles. Get involved in the community, answer questions, comment on other posts, etc. If you want to be successful with a particular tool, it really helps to be tuned in to their community. It also helps you keep up with new feature releases and any technical issues you should be aware of. &lt;/p&gt;

&lt;p&gt;And lastly, this all goes back to adding credibility to your work in this particular platform, and will help you generate leads and close more deals. I've often had leads contact me based on forum posts I wrote. Your previous posts can also be used as example work when applying to jobs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tip #3 - Create a Highly Specific Blog
&lt;/h2&gt;

&lt;p&gt;Now that you have that niche chosen and forum profile setup, it's time to start working on your own blog. There's no need to build your own site from scratch, but if that's your niche, then by all means, go for it! For &lt;a href="https://blog.greenflux.us/"&gt;mine&lt;/a&gt;, I just used Hashnode, because I'm not a frontend dev, and not trying to land frontend work. &lt;/p&gt;

&lt;p&gt;Whatever you use, don't worry so much about page views or distributing the posts on social. Try to think of the blog as more of a credential to show to existing leads to help close a deal, as opposed to it being a way to generate new leads. &lt;/p&gt;

&lt;p&gt;For me, once I had a decent library of posts built up, I started using them in proposals as a way to show a specific example of my work that was related to the job. At that point, I barely had to write more than a quick intro and closing, then drop in a link to the most relevant blog post. This worked wonders for me on UpWork proposals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip #4 - Build a Personal, or Company Brand
&lt;/h2&gt;

&lt;p&gt;Ok, you're blog is set up and you're active on related forums to start getting your name out there. Now it's time to start developing your brand. This can be as simple as using your own name and headshot, or it could mean picking a business name, domain, logo, etc. Either way, make your content easy to recognize across various forums, freelancer profiles, blogs, social, etc, by standardizing on the profile pic, name bio, etc. &lt;/p&gt;

&lt;p&gt;Next, cross-link all of those profiles! Make sure every one has a link back to your blog and freelancer profiles. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tip #5 - Partner Programs &amp;amp; Vendor Listings
&lt;/h2&gt;

&lt;p&gt;Getting listed as a partner or vendor is another great way to generate leads. And it looks good on your profile, and will instill confidence in your prospective clients. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Partner/Affiliate Programs&lt;/strong&gt;: Lots of platforms have partner programs where you can apply to be listed as a service provider from their community. Some are as easy as filling out a form, while others have interviews or exams involved. See what's available for the platforms and services you plan to use, and apply to be a partner or affiliate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vendor Listings&lt;/strong&gt;: Government and educational institutions tend to have systems where contractors can apply to be listed as a vendor. See if you can get listed for your local university, or county or city municipality. Even if you never bid on a job, being listed as a vendor is both free advertising, and a credential you can show off. &lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts on Freelancer Sites for 2024
&lt;/h2&gt;

&lt;p&gt;UpWork and Fiverr have changed a LOT over the last few years, and even more so with the release of ChatGPT. Between the spam and scams on both sides of the job posts, and all the fees involved, these platforms aren't nearly as useful as they once were. However, I still encourage you to create a profile, upload a portfolio, and link to your profiles on your blog and socials. More web presence is better, and it's good to have the profile set up ahead of time in case you find a client who prefers to use it for payment. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try, but Don't Buy&lt;/strong&gt;: Although I wouldn't recommend putting much effort (or money!) into applying to jobs on freelancer sites in 2024, you still need contracts and payment processing. &lt;/p&gt;

&lt;p&gt;Instead of applying to jobs, focus on building your web presence and establish yourself as an expert in your chosen niche. Then, bring your leads to a freelancer site to manage the contract, payment, and to collect a review. There's still value in those services, so don't write these freelancer sites completely off, just yet. &lt;/p&gt;

&lt;h2&gt;
  
  
  2024, and Beyond!
&lt;/h2&gt;

&lt;p&gt;Freelancing has been an amazing journey for me, and I encourage everyone else who is interested to give it a try. Whether you're already freelancing and looking for ways to expand, or just getting ready to take the first step, I wish you all the best of luck in 2024 and beyond! Feel free to reach out with any questions or comment below to share your freelancer story. &lt;/p&gt;

</description>
      <category>freelance</category>
      <category>nocode</category>
      <category>lowcode</category>
      <category>developer</category>
    </item>
    <item>
      <title>Building a signature capture widget with an Appsmith Iframe and SignaturePad.js</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Thu, 14 Dec 2023 15:22:28 +0000</pubDate>
      <link>https://dev.to/appsmith/building-a-signature-capture-widget-with-an-appsmith-iframe-and-signaturepadjs-fkn</link>
      <guid>https://dev.to/appsmith/building-a-signature-capture-widget-with-an-appsmith-iframe-and-signaturepadjs-fkn</guid>
      <description>&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Build a signature capture widget using custom code in an Appsmith Iframe widget srcDoc field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capture signatures as images, then access the image outside of the iframe&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An Appsmith Account&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A new or existing app&lt;/strong&gt; - where you want to add the signature capture widget&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The iframe widget is like an escape hatch that leaves the low-code environment of Appsmith and allows you to write full web apps using any framework of your choice. If there's something you can't do with one of our 45+ widgets, you can probably do it in an iframe. &lt;/p&gt;

&lt;p&gt;For instance, although we don't have a native signature capture widget (&lt;a href="https://github.com/appsmithorg/appsmith/issues/7960" rel="noopener noreferrer"&gt;yet&lt;/a&gt;), you can easily build one with just a few lines of JavaScript, and the signaturePad.js library. &lt;/p&gt;

&lt;h2&gt;
  
  
  Add an Iframe Widget
&lt;/h2&gt;

&lt;p&gt;Add an iframe where you want the signature capture, and paste the following code in the srcDoc field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"signature-pad"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"clear"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"save"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;signature-pad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;signaturePad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SignaturePad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgb(250,250,250)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;signaturePad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;dataURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signaturePad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dataURL&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the event listener on the &lt;strong&gt;SAVE&lt;/strong&gt; button that posts a message to the parent window.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Access the Signature Image
&lt;/h2&gt;

&lt;p&gt;Once the &lt;strong&gt;SAVE&lt;/strong&gt; button is clicked, the image will be accessible at &lt;code&gt;Iframe1.message.data&lt;/code&gt;. You can view it in a regular Image widget, or view the raw data in a Text widget. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07fgd31gm3xh728pegnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07fgd31gm3xh728pegnv.png" alt="Screenshot"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;h2&gt;
  
  
  Trigger an Event when saving
&lt;/h2&gt;

&lt;p&gt;You may want to save the image back to a database, or send it in an email after signing. The Iframe widget has an &lt;a href="https://docs.appsmith.com/reference/widgets/iframe#events" rel="noopener noreferrer"&gt;onMessageReceived&lt;/a&gt; property, where you can select which Actions to run when a message is posted from the iframe. The Action selector also allows you to add callback functions, so you can chain together Actions, and do things like saving the image to Amazon S3, then saving the new URL back to a record in MySQL.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Iframe widget can easily be used to create custom widgets, and new interfaces to capture and display data. By adding just a few lines of code, a Signature Capture widget can be built and integrated with the rest of your app. &lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js" rel="noopener noreferrer"&gt;cdn.jsdelivr.net/npm/signature_pad@4.0.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.appsmith.com/reference/widgets/iframe#docusaurus_skipToContent_fallback" rel="noopener noreferrer"&gt;Iframe Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://community.appsmith.com/content/guide/iframe-experiments-extending-appsmith-custom-iframe-code" rel="noopener noreferrer"&gt;Iframe Experiments: Extending Appsmith with custom iframe code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>lowcode</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a CRUD app with Google Sheets</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Thu, 07 Dec 2023 14:33:58 +0000</pubDate>
      <link>https://dev.to/appsmith/building-a-crud-app-with-google-sheets-41hm</link>
      <guid>https://dev.to/appsmith/building-a-crud-app-with-google-sheets-41hm</guid>
      <description>&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This tutorial covers the basics for creating a CRUD (Create, Read, Update, Delete) app using Google Sheets as the datasource. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An Appsmith account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Google account&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Google Sheets is actually our most used datasource in Appsmith! It's great for quickly prototyping an app, or building a PoC (proof of concept) or MVP (minimum viable product). &lt;/p&gt;

&lt;p&gt;For this tutorial, we'll be using a mock dataset for an events app at a software company. Start out by copying the sample sheet to your Google account, and give it a unique name so it's easy to find from Appsmith.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1u9_ZSxeu1JtQdV9f5CSwpE1WVnaAR3bwYmXD4EImir8/copy"&gt;Sample Events sheet&lt;/a&gt; &amp;lt;= Make a copy&lt;/p&gt;

&lt;p&gt;Next, we'll create a Google Sheets datasource in Appsmith, and then add APIs and a table widget to display and edit the sheet data. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
   Create a Google Sheets Datasource
&lt;/h2&gt;

&lt;p&gt;Start out by creating a new app, and then add a Google Sheets datasource. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E-Zr6Lto--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%25207.46.40%2520AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E-Zr6Lto--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%25207.46.40%2520AM.png" alt="gsheets datasource" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; In the Appsmith editor, click the Datasources [+] button and choose Google Sheets&lt;/li&gt;
&lt;li&gt; Name the datasource &lt;/li&gt;
&lt;li&gt; Set the Permissions to: &lt;code&gt;Read / Write / Delete | Selected google sheets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Click Save and authorize, then choose your Google account and authorize Appsmith to connect&lt;/li&gt;
&lt;li&gt; In the next screen, find and select your new copy of the Events sheet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: Best practice is to create a new datasource for each sheet, instead of using the &lt;em&gt;Read / Write / Delete | ALL google sheets&lt;/em&gt; option. &lt;/p&gt;

&lt;p&gt;Keep in mind, if you choose ALL Google Sheets, and you share the workspace with someone else as a developer or admin, they will be able to access all of your Google Sheets!&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
   Get data from Google Sheets
&lt;/h2&gt;

&lt;p&gt;Next, we'll add an API to get data from the sheet. Make sure to create the new API under the Google Sheets datasource you just created. You can use the [+] New query button on the Google Sheets datasource, or the [+] Query/JS button, then select the Google Sheets datasource. &lt;/p&gt;

&lt;p&gt;Pro Tip: You can also use the keyboard shortcut &lt;code&gt;cmd-shift-+&lt;/code&gt; to add a new API. More keyboard shortcuts &lt;a href="https://docs.appsmith.com/advanced-concepts/more/keyboard-shortcuts#docusaurus_skipToContent_fallback"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add a new Google Sheets API and name it &lt;code&gt;getRows&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Configure as follows:\
Operation: &lt;em&gt;Fetch Many&lt;/em&gt;\
Entity: &lt;em&gt;Sheet Row(s)&lt;/em&gt;\
Spreadsheet: The Events sheet you just copied\
Sheet: &lt;em&gt;events&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Click RUN&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2lNBA55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.39.20%2520AM.png%3Fitok%3DiqM4Ylk0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2lNBA55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.39.20%2520AM.png%3Fitok%3DiqM4Ylk0" alt="gsheets getrows" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should get back a response with data from the spreadsheet. Now, on the right panel under Add new widget, click the &lt;em&gt;Table&lt;/em&gt; binding shortcut. This will add a table widget to the canvas and automatically connect it to the getRows API. Alternatively, you can drag in a table widget, then set the Table Data property to &lt;code&gt;{{getRows.data}}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notice the toast message about the getRows API running on page load now? Appsmith automatically sets a query to run on page load if it's connected to a widget. This way the widget will have data to display when the app first opens. You can also set a query to run on page load in the Settings tab for that query. &lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
   Add a row to Google Sheets
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.appsmith.com/reference/widgets/table#docusaurus_skipToContent_fallback"&gt;table widget&lt;/a&gt; has an awesome new feature for adding a row directly from the table, instead of using a form widget. First, we'll enable adding a row, then we'll create the new API, and lastly, we'll connect the new API to the table widget. &lt;/p&gt;

&lt;p&gt;To get started, select the table widget and find the Adding a row section at the bottom of the property pane:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Adding a row &amp;gt; 

&lt;ol&gt;
&lt;li&gt; Allow adding a row =&amp;gt; ON&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then go up to the column settings for the table widget:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Data &amp;gt; Columns &amp;gt;

&lt;ol&gt;
&lt;li&gt; Click the checkbox to mark all columns as editable&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt; On the top of the table widget, click the + Add new row button

&lt;ol&gt;
&lt;li&gt; Enter some dummy data in the new row, but don't click &lt;em&gt;Save row&lt;/em&gt; yet!\
This will give us a draft row object to use in the addRow API. &lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sgUwuhFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.52.34%2520AM.png%3Fitok%3DA0FPbMyE" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sgUwuhFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.52.34%2520AM.png%3Fitok%3DA0FPbMyE" alt="edit table" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, create a new API under the Google Sheets datasource. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add new API: Insert One &amp;gt; Sheet row&lt;/li&gt;
&lt;li&gt; Name the API &lt;code&gt;addRow&lt;/code&gt; &lt;/li&gt;
&lt;li&gt; Set the Row object to: &lt;code&gt;{{Table1.newRow}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HhhPJ7----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.54.51%2520AM.png%3Fitok%3DidH6lnJ8" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HhhPJ7----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.54.51%2520AM.png%3Fitok%3DidH6lnJ8" alt="save row api" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see the data you entered for the new row in the evaluated value pane. Now, head back to the table widget properties to connect the API to the SAVE button. Once the addRow API runs, you'll want to run the getRows API again to update the data in the table widget. This can easily be done using the callback option in the action selector. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OJalODz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.45.02%2520AM.png%3Fitok%3D1gsnU6Qk" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OJalODz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/styles/wide/public/2023-08/Screenshot%25202023-08-06%2520at%25209.45.02%2520AM.png%3Fitok%3D1gsnU6Qk" alt="addrow" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Adding a row &amp;gt; 

&lt;ol&gt;
&lt;li&gt; On Save =&amp;gt; addRow API

&lt;ol&gt;
&lt;li&gt; Callbacks: On Success =&amp;gt; &lt;em&gt;getRows&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, head back to the new row you started to add on the table widget and click Save row. You should see the new row added to the sheet, and the table widget updated with the new data. &lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
   Updating a row in Google Sheets
&lt;/h2&gt;

&lt;p&gt;Next, we'll add a new API for updating a row and use the table widget's row editing feature. This will be similar to the addRow API, but now we must also specify the rowIndex of the row to update. Start out by creating the new API. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add new API: Update One &amp;gt; Sheet Row&lt;/li&gt;
&lt;li&gt; Name the API &lt;code&gt;updateRow&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Set body to &lt;code&gt;{{Table1.updatedRow}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice how there's a new SAVE/DISCARD column in the table widget now? That gets added when you enable row editing, but you have to configure which action to run when the user clicks save. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Columns &amp;gt; Save/Discard (click the gear icon)&lt;/li&gt;
&lt;li&gt; Set the On Save to &lt;code&gt;updateRow&lt;/code&gt;

&lt;ol&gt;
&lt;li&gt; Callback: On Success =&amp;gt; &lt;code&gt;getRows&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NBJzdWOi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%252010.00.51%2520AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NBJzdWOi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%252010.00.51%2520AM.png" alt="updating a row" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you should be able to edit a row, then click SAVE to update the sheet and refresh the table widget. &lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
   Deleting a row in Google Sheets
&lt;/h2&gt;

&lt;p&gt;Lastly, we'll add an API for deleting a row, then connect it to a new button in the table widget. Start out by adding a new button column to the table widget, then create an API and link it to the new button. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Columns &amp;gt; [+] Add new column&lt;/li&gt;
&lt;li&gt; Set the column name to &lt;code&gt;Delete&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Click the gear icon to open the column settings&lt;/li&gt;
&lt;li&gt; Set Column type to &lt;em&gt;Icon Button&lt;/em&gt;, and select the &lt;em&gt;trash&lt;/em&gt; icon&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, add the deleteRow API. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add new API: Delete One &amp;gt; Sheet Row&lt;/li&gt;
&lt;li&gt; Name the API &lt;code&gt;deleteRow&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Set the rowIndex to &lt;code&gt;{{Table1.triggeredRow.rowIndex}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lastly, connect the API to the new delete button. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Table Widget &amp;gt; Columns &amp;gt; Delete (click the gear icon)&lt;/li&gt;
&lt;li&gt; OnClick =&amp;gt; &lt;em&gt;deleteRow&lt;/em&gt;

&lt;ol&gt;
&lt;li&gt; Callback: On Success =&amp;gt; &lt;em&gt;getRows&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e0mSDe7i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%252010.06.28%2520AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e0mSDe7i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://community.appsmith.com/sites/default/files/2023-08/Screenshot%25202023-08-06%2520at%252010.06.28%2520AM.png" alt="delete row" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! You now have APIs for Creating, Reading, Updating, and Deleting data in Google Sheets; a complete CRUD app without writing a single line of code. &lt;/p&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Google Sheets is a great choice for a backend when you need to quickly throw together an app, build a PoC or test out an idea. And Appsmith's native Google Sheets connector makes it easy to quickly build a full CRUD app on top of your sheets data. &lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.appsmith.com/connect-data/reference/querying-google-sheets"&gt;Appsmith Docs: Google Sheets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.appsmith.com/connect-data/how-to-guides/connect-datasource"&gt;Appsmith Docs: Connecting to Datasources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>crud</category>
      <category>appsmith</category>
    </item>
    <item>
      <title>Slack Workflow Builder: Send Messages in 2 Simple Steps</title>
      <dc:creator>Joseph Petty</dc:creator>
      <pubDate>Thu, 12 Oct 2023 12:49:11 +0000</pubDate>
      <link>https://dev.to/appsmith/slack-workflow-builder-send-messages-in-2-simple-steps-3ifh</link>
      <guid>https://dev.to/appsmith/slack-workflow-builder-send-messages-in-2-simple-steps-3ifh</guid>
      <description>&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This guide will cover: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to create a new workflow in Slack using a webhook trigger&lt;/li&gt;
&lt;li&gt;how to trigger that workflow from Appsmith and send a message to a channel&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An Appsmith account&lt;/li&gt;
&lt;li&gt;A Slack account, and a workspace you own or have permission to install workflows on&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Slack has been rolling out some new updates recently, and the UI changes have many users upset and looking for &lt;a href="https://www.reddit.com/r/Slack/comments/16iiphb/hate_the_new_ui/" rel="noopener noreferrer"&gt;ways to re-enable the old UI&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u71jarh609bv0iidid4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u71jarh609bv0iidid4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But last week, after the whiplash from the UI changes wore off, I noticed this new Automation tool. It's a workflow builder that allows you to chain together different actions and automate tasks in Slack and other connected platforms, like a basic version of Zapier or n8n. &lt;/p&gt;

&lt;p&gt;Slack already had support for sending a message to a channel using a webhook, but now you can send webhooks to a workflow. This means you can trigger a series of actions, including channel messages, adding a row to Google Sheets, creating a Notion doc, and all kinds of other actions. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud68ku4by3cy8ity5r29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud68ku4by3cy8ity5r29.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a New Workflow in Slack&lt;br&gt;
First, create a new workflow in Slack, and set it up to send a message to a specific channel. &lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/70_4jjUwlK4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the Webhook API in Appsmith&lt;br&gt;
Next, create a new POST API in Appsmith, and sent a test message. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/bVqCleew8bs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffn7dt7bk2d8osbg2bdbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffn7dt7bk2d8osbg2bdbg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just 2 simple steps to create the workflow and trigger it from Appsmith. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Slack workflows also have integrations with SalesForce, Notion, Google Sheets, and a bunch of other services. With the workflow published and a POST API set up, you can now integrate Slack with Appsmith, and automate your team's business tasks more seamlessly. We'd love to hear how you're using Slack and Appsmith at work! Or if you have ideas for a tutorial, feel free to post below and request. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
