-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Checklist I have: - [ ] run the content through Grammarly - [ ] linked to sample apps when relevant - [ ] added the meta description for each page in the PR - [ ] minimized the callouts and added only when necessary - [ ] added the `queryString` parameter to the Tabs (if used) - [ ] masked PII in images. For example, login credentials, account details, and more - [ ] added images only when necessary - [ ] deleted the images that are no longer used for the updated pages in the PR - [ ] followed the image file naming convention while renaming or adding new images. (Use lowercase letters, dashes between words, and be as descriptive as possible) - [ ] used the `<figure/>` tag instead of a markdown representation for images - [ ] added the `<figcaption/>` tag to add a caption to the image - [ ] added the `alt` attribute in the `<img/>` tag - [ ] verified and updated the cross-references or created redirect rules for the changed or removed content - [ ] reviewed and applied the style changes for UI formatting. For example, Bold the UI elements(Buttons on screen) used in the doc. --------- Co-authored-by: sbalaji1192 <[email protected]>
- Loading branch information
1 parent
16c163a
commit d225b7e
Showing
7 changed files
with
926 additions
and
45 deletions.
There are no files selected for viewing
324 changes: 281 additions & 43 deletions
324
website/docs/build-apps/how-to-guides/Create-Custom-Widgets-Using-Iframe.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,293 @@ | ||
# Create Custom Widgets Using Iframe | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
Appsmith offers a wide range of widgets for building applications. Still, sometimes you may need a custom widget for a specific purpose, such as a calendar, accordion, social media widget, etc. In such cases, you can create the widget in HTML or a language like React and display it in the Iframe widget. | ||
# Create Custom Widgets | ||
|
||
Lets create a custom Code Editor Widget with the [Ace Code Editor Library](https://ace.c9.io/). | ||
This guide shows how to create a Custom widget using React. | ||
|
||
1. In the **srcDoc** property, add the following code: | ||
|
||
While Appsmith provides an extensive array of built-in widgets for application development, there are instances where your project demands a widget tailored to specific requirements. Appsmith's Custom widget allows you to integrate unique functionalities with your HTML, CSS, and JavaScript code, whether it's a personalized calendar, accordion, or social media widget. | ||
|
||
:::info | ||
Currently, only cloud users have access to the Custom widget. | ||
::: | ||
|
||
## Configure Custom Widget | ||
|
||
1. Drop a [Custom widget](/reference/widgets/custom) on the canvas. | ||
|
||
2. Click the **Edit Source** button on the property pane to configure the code for the Custom widget. Within the Custom widget builder, you can add JS, CSS, and HTML code, and the Custom widget is reloded automatically on the preview section on the left of the Custom widget Builder. | ||
|
||
|
||
3. In the [Custom widget builder](/reference/widgets/custom#custom-widget-builder), remove the default component code in HTML, CSS, and JS editors, and import the required libraries. | ||
|
||
<dd> | ||
|
||
To import a third-party library, you have two options: UMD and ESM. Use trusted CDN providers like [jsDelivr](https://www.jsdelivr.com/) or [UNPKG](https://unpkg.com/) for library imports. | ||
|
||
* For UMD, include the library with a script tag in the HTML file: | ||
|
||
```html | ||
<script src="link-to-the-UMD-file"></script> | ||
``` | ||
|
||
* For ESM, use an import statement at the top of the JavaScript file: | ||
|
||
```js | ||
import ThirdPartyComponent from "link-to-the-ESM-file"; | ||
``` | ||
</dd> | ||
|
||
4. Add the code for the Custom widget within the relevant tabs based on your library requirements. | ||
|
||
<dd> | ||
|
||
|
||
:::warning | ||
* Wait for the parent application to be ready before accessing the model or triggering events in the custom widget. Use [appsmith.onReady](/reference/widgets/custom#onready) and pass a handler function, which is triggered when the parent application is ready, initiating the rendering of your component from this function. | ||
|
||
* For dynamic updates in response to model changes, such as new data from a query, use [appsmith.onModelChange](/reference/widgets/custom#onmodelchange). Pass a handler to this function, and it gets invoked each time the model undergoes a modification. | ||
::: | ||
|
||
*Example*: Image carousel using the [React image gallery](https://www.jsdelivr.com/package/npm/react-image-gallery) library, import the necessary libraries and render the app function accordingly. | ||
|
||
<Tabs> | ||
<TabItem value="html" label="HTML"> | ||
|
||
```html | ||
<head> | ||
<style type="text/css" media="screen"> | ||
#editor { | ||
position: absolute; | ||
top: 40px; | ||
right: 0; | ||
bottom: 0; | ||
left: 0; | ||
<!-- no need to write html, head, body tags, it is handled by the widget --> | ||
<div id="root"></div> | ||
|
||
<!-- Including the stylesheet for the React Image Gallery from the specified CDN. --> | ||
|
||
<link href=" | ||
https://cdn.jsdelivr.net/npm/[email protected]/styles/css/image-gallery.min.css | ||
" rel="stylesheet"> | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="jss" label="JS" default> | ||
|
||
|
||
|
||
```js | ||
// Importing necessary React libraries | ||
import React from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm' | ||
import reactDom from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm' | ||
|
||
// Importing the ImageGallery component from the specified CDN | ||
import ImageGallery from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'; | ||
|
||
// App component using the ImageGallery with the specified images | ||
function App() { | ||
// Array of image objects for the carousel | ||
const images = [ | ||
{ | ||
original: "https://picsum.photos/id/1018/1000/600/", | ||
thumbnail: "https://picsum.photos/id/1018/250/150/", | ||
}, | ||
{ | ||
original: "https://picsum.photos/id/1015/1000/600/", | ||
thumbnail: "https://picsum.photos/id/1015/250/150/", | ||
}, | ||
{ | ||
original: "https://picsum.photos/id/1019/1000/600/", | ||
thumbnail: "https://picsum.photos/id/1019/250/150/", | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="editor">function foo(items) { | ||
var x = "All this is syntax highlighted"; | ||
return x; | ||
}</div> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src-min-noconflict/ace.min.js" type="text/javascript" charset="utf-8"></script> | ||
<script> | ||
var editor = ace.edit("editor"); | ||
editor.setTheme("ace/theme/monokai"); | ||
editor.session.setMode("ace/mode/javascript"); | ||
editor.on("change", function() { | ||
// Get the value of the editor and send it to the parent window | ||
var code = editor.getValue(); | ||
window.parent.postMessage(code, "*"); | ||
}); | ||
</script> | ||
``` | ||
This code creates a code editor widget using the Ace code editor library and sends the entered code to the [parent window](#communication-between-app-and-iframe) when the "Submit Code" button is clicked. | ||
|
||
|
||
2. Next, add Text widget and sets its **Text** property to: | ||
]; | ||
|
||
return <ImageGallery.default items={images} />; | ||
} | ||
|
||
// Rendering the App component when widget is ready | ||
appsmith.onReady(() => { | ||
reactDom.render(<App />, document.getElementById("root")); | ||
}); | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
</dd> | ||
|
||
|
||
5. To pass data from Appsmith to the Custom widget, use the **Default model** property of Custom widget. You can bind data from queries or widgets using mustache bindings `{{}}`. | ||
|
||
<dd> | ||
|
||
*Example:* For the image slider, add code that captures image or document URL, like: | ||
|
||
|
||
```js | ||
{ | ||
"data": [ | ||
"https://img.freepik.com/premium-vector/vector-illustration-open-passport-template-document-travel-concept-passport-sample_212168-95.jpg?w=996", | ||
"https://img.freepik.com/free-vector/flat-design-driving-license-template_23-2149944210.jpg?w=1060&t=st=1680096311~exp=1680096911~hmac=2ad65c94c28bc6db27104d8e791069f04af44763e5c07bafeddea1a89ec6dc5b", | ||
"https://as1.ftcdn.net/v2/jpg/03/45/67/40/1000_F_345674072_QwzzCNH6PElHQxsow7DtAr50TyGmcYGs.jpg" | ||
] | ||
} | ||
|
||
``` | ||
|
||
To dynamically add data, whether from a query or a widget, you can use something like: | ||
|
||
|
||
```js | ||
{"data": [ | ||
{{tbl_users.selectedRow.passport}}, | ||
// Add more entries as needed | ||
]} | ||
``` | ||
|
||
|
||
</dd> | ||
|
||
6. To retrieve the data provided to the **Default model** property, use `appsmith.model.propertyName` within the JavaScript section of the Custom widget builder. | ||
|
||
|
||
<dd> | ||
|
||
*Example:* For the image carousel, use a map function to dynamically render images sourced from the **Default model** property. | ||
|
||
```js | ||
{{Iframe1.message}} | ||
|
||
function App() { | ||
// Fetching image URLs | ||
// highlight-next-line | ||
const imageUrls = appsmith.model.data; | ||
|
||
// Generating dynamic images using the map function | ||
// highlight-next-line | ||
const images = imageUrls.map((url, index) => ({ | ||
// highlight-next-line | ||
original: url, | ||
// highlight-next-line | ||
thumbnail: url | ||
// highlight-next-line | ||
})); | ||
|
||
// Returning the ImageGallery component with the generated images | ||
return <ImageGallery.default items={images} />; | ||
} | ||
|
||
//To access data in CSS use var(--appsmith-model-{property-name} | ||
``` | ||
|
||
</dd> | ||
|
||
|
||
7. To pass data from the Custom widget to Appsmith, use the `updateModel` property within your JS code to save or update data. Once the model is updated, you can retrieve the value using `{{Custom.model.propertyname}}` within any widget or query. | ||
|
||
<dd> | ||
|
||
*Example*: To retrieve the index of the current slide, add an `onSlide` event handler(provided by the library), and use `updateModel` to store the selected index, like: | ||
|
||
```js | ||
//JS | ||
function App() { | ||
const imageUrls = appsmith.model.data; | ||
|
||
// Generating dynamic images using the map function | ||
const images = imageUrls.map((url, index) => ({ | ||
original: url, | ||
thumbnail: url, | ||
})); | ||
|
||
// highlight-next-line | ||
const _onSlide = (index) => { | ||
// You can perform any actions related to sliding here | ||
// highlight-next-line | ||
console.log("Slid to index", index); | ||
// highlight-next-line | ||
appsmith.updateModel({ selectedIndex: index }); | ||
// highlight-next-line | ||
}; | ||
|
||
return ( | ||
// highlight-next-line | ||
<ImageGallery.default items={images} showIndex={true} onSlide={_onSlide} /> | ||
); | ||
} | ||
|
||
``` | ||
This retrieves the entered code from the editor and displays it in a Text widget using the `message` reference property. | ||
|
||
With this setup, users can edit the code in the code editor, and when the submit button is clicked, the entered code would be processed or displayed as desired. | ||
To display data in a Text widget, set its **Text** property to: | ||
|
||
```js | ||
{{ImageCarousel.model.selectedIndex}} | ||
|
||
//ImageCarousel, name of the custom widget | ||
``` | ||
|
||
</dd> | ||
|
||
|
||
8. For widget interaction, you can create events using the **Add Event** button on the Custom widget and use the `triggerEvent` property inside the Custom widget builder. | ||
|
||
<dd> | ||
|
||
*Example:* To trigger an action on Appsmith when the image is slid, use the following code: | ||
|
||
<Tabs> | ||
<TabItem value="js" label="JS" default> | ||
|
||
```js | ||
const _onSlide = (index) => { | ||
// You can perform any actions related to sliding here | ||
console.log("Slid to index", index); | ||
// highlight-next-line | ||
appsmith.triggerEvent("onSlide"); | ||
appsmith.updateModel({ selectedIndex: index }); | ||
}; | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
In the Custom widget, create a new event with the same name `(i.e onSlide)` as defined in the function, and configure it to execute an action. | ||
|
||
|
||
<div style={{ position: "relative", paddingBottom: "45.52%", height: "0", width: "82%" }}> | ||
<iframe src="https://demo.arcade.software/4gK4YuptByPSJPeB0cda?embed" frameBorder="0" loading="lazy" allowFullScreen style={{ position: "absolute", top: "0", left: "0", width: "100%", height: "100%", colorScheme: "light" }} title="Appsmith | Connect Data"></iframe> | ||
</div> | ||
|
||
</dd> | ||
|
||
9. To customize your widget's appearance, configure the CSS code, and use Appsmith's [CSS API](/reference/widgets/custom#css-api) to dynamically adjust styles based on the app's theme. | ||
|
||
|
||
<dd> | ||
|
||
|
||
<Tabs> | ||
|
||
<TabItem value="css" label="CSS"> | ||
|
||
```css | ||
#root { | ||
// highlight-next-line | ||
background-color: var(--appsmith-theme-primaryColor); | ||
padding: 20px; | ||
// highlight-next-line | ||
border-radius: var(--appsmith-theme-borderRadius); | ||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||
} | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
See the sample app for the [Image carousel](https://app.appsmith.com/app/untitled-application-1/page1-65a77eecc7165278ae63151b). | ||
|
||
|
||
|
||
|
||
</dd> | ||
|
||
|
||
## Sample apps | ||
|
||
* [Image Annotator](https://app.appsmith.com/app/image-annotator/image-labeler-react-659fb55bf645785f6fc6f9c9) | ||
* [Data grid widget](https://app.appsmith.com/app/data-grid/page1-6597ff5559aa5450e0eb4eb9) | ||
* [Signature Pad widget](https://app.appsmith.com/app/signature-pad/page1-6597af1e21e083222a47e366) | ||
|
||
|
||
<ZoomImage | ||
src="/img/custom-widget-code.png" | ||
alt="Display images on table row selection" | ||
caption="Custom Code Editor" | ||
/> |
Oops, something went wrong.
d225b7e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
appsmith-docs – ./
appsmith-docs-git-main-get-appsmith.vercel.app
docs.appsmith.com
appsmith-docs-nu.vercel.app
appsmith-docs-get-appsmith.vercel.app