The Low-coders Guide To JavaScript

Vihar Kurama
Posted by Vihar KuramaPublished on Oct 17, 2022
6 min read
JS Transformation Title

Appsmith falls squarely on the side of low-code in the low-code-no-code fence. We offer you the flexibility to write code when you want to. In keeping with the spirit of low-code, we also make it easier than the heavy-code writing experience without trading off the God Mode-powers you are used to.

This post maps the different ways and places you can write code on Appsmith to scenarios where they are most useful. You will learn how you can use JavaScript

  • to present data in and play with data from widgets

  • transform data for your and your end-users’ needs

  • conditionally execute code to achieve unique end-user experiences

For our example, we will see how to build a dashboard for historical analytics of the Olympics, connecting to data on a PostgreSQL database.

Present data right

While our widgets can present data with assisted query bindings, Javascript makes it easier to bind transformed data per a widget's expected datatype.

Let the bindings begin

One small step in the code, one giant leap for your app

If you have connected your database to Appsmith and run a successful query as we already have, you can present the query’s response using JavaScript with any widget, passing the .data operator to the query.

Snippet used

{{ fetch_athelets.data }}

Methods to the madness

As you build your app, you will often need to show data differently from how it appears in the query response and consequently, the widget. JavaScript methods are natively supported in Appsmith.

  • map.(), used directly in the binding on a widget’s data property, helps show only those row values that match data attributes as defined in the map.() method.

Snippet used

{{
fetch_athelets.data.map((item) => {
      return {
	id: item.id,
        name: item.name,
        team: item.team,
        sex: item.sex,
        season: item.season,
	sport:item.sport
      };
    });
}}

map.() shows the values for just the names of players, the team they belong to, the season, and the sport.
  • Like map.(), you can use the .filter() method in a widget’s query bindings to refine the data presented.

Snippet used

{{
fetch_athelets.data.map((item) => {
      return {
				id: item.id,
        name: item.name,
        team: item.team,
        sex: item.sex,
        season: item.season,
				sport:item.sport
      };
    }).filter((item) => {
        return item.season == "Summer";
      });;
}}
Using `filter.()` atop `map.()` lets us show the data for just the Summer Olympics.

🥳 Auto-complete contextually assists in picking supported methods, eliminating guess-work and repetitive code writes.

Objectifying data

The Table expects data in the Array format. The Select widget, though, expects data in the Array<{ "label": "string", "value": "string" }> format. This format or datatype is called an object.

Snippet used

{{ fetch_seasons.data.map(i => ({
	label: i.season,
	value: i.season
})) }}
Our app now has two simple filters.

Functions on the run

The Select also expects unique values and throws a fit when you have duplicate values in your records. To show unique picklist options, use IIFEs and remove duplicates in the data binding.

🏃 An Immediately Invoked Function Expression (IIFE) is a JavaScript function that runs as soon as it is defined.

Snippet used

function make_unique() {
  let data = fetch_seasons.data.map((i) => ({
    label: i.game_season,
    value: i.game_season,
  }));   const key = "label";
  const arrayUniqueByKey = [
    ...new Map(data.map((item) => [item[key], item])).values(),
  ];
  return arrayUniqueByKey;
}()

Make your queries smarter

Pro devs will recognize we have taken simpler, non-smart routes to present data thus far. In reality, there are browser performance considerations and limitations to using methods or writing just about any code on the full query response.

Using Appsmith to optimize queries and thus, your app’s performance, is easy.

Dynamism

A smarter way to present filtered data is to bake in dynamic triggers per action taken on widgets in the query itself irrespective of the query language. Because, JavaScript. 🤯

You can do that using {{ }} in Appsmith.

Snippet used

SELECT name, sex, age, team, year, season, city, sport, event, medal
FROM public."athelete"
WHERE
	season = {{filter_season.selectedOptionValue}}
ORDER BY year LIMIT 100;
We write a SQL query that includes a JavaScript snippet under the WHERE clause. filter_season is the name of the Select widget and selectedOptionValue is the property that we bind to the query.

Refreshed and informed

Now that you have the filtered data from your smarter query, you will need to provision for data refreshes triggered by widgets. For example, if your users select an option from the Select widget, whichever widget presents the data—in this case, the Table—needs to now present the filtered view.

This is super-easy with Appsmith, thanks to JavaScript in widget props.

  • Properties like onChange and onClick can take JavaScript to refresh the data in a widget specific to an end-user action.

    onChange and onClick take {{fetch_athelets_with_filters.run()}} to refresh the data by the Select widget’s options.

  • Additionally, you can also show alerts on your app’s UI to inform your end-users of successful query execution.

Snippet used

{{
    fetch_athelets_with_filters.run(
      () =>
        showAlert(
          "Showing data from " + filter_season.selectedOptionValue + " season",
          "success"
        ),
      () => showAlert("Query failed with an error", "error")
    );
}} 
~~Kill~~ Call confirmed?

Transformed

For scenarios where you need to show data from different rows or even entirely different tables on your database, the Appsmith Query Editor assists with JavaScript methods.

  • Add multiple dynamic conditions from widgets and transform your query response with JavaScript methods.

Snippet used

SELECT name, sex, age, team, year, season, city, sport, event, medal
FROM public."athelete"
WHERE
	season = {{filter_season.selectedOptionValue}} and
	year IN {{ filter_year.selectedOptionValues.join(',') }} and
	sport = {{filter_sport.selectedOptionValue}}
ORDER BY year LIMIT 100; 
The Evaluated Value pane—we really a better name for it—resolves JavaScript methods like `.join` to help see what a response may look like.
  • Auto-complete helps you select supported functions within {{ }} so you don’t feel the need peek at StackOverflow.

Make your code performant

Appsmith comes with a few JavaScript libraries out of the box to help you offer desired features and performance to your end-users without code circus. Use them inside {{ }}, or JS Objects, just like any other binding or transformation.

Lodash for the win

Lodash helps you write performant JavaScript with less code. Use _. to invoke Lodash methods anywhere you write JavaScript in Appsmith.

  • Remove duplicate values using the _.uniqWith, and _.isEqual from Lodash inside your bindings.

Snippet used

{{
    _.uniqWith(fetch_events.data.map((i) => i.sport))
      .map(
        (i) => ({
          label: i,
          value: i,
        }),
        _.isEqual
      )
}}
A binded query shows values by the unique names of sports in the Olympics.
  • Use _union(), to add more items to your array.

Snippet used

{{
    _.union(
      _.uniqWith(fetch_events.data.map((i) => i.sport)).map(
        (i) => ({
          label: i,
          value: i,
        }),
        _.isEqual
      ),
      [{ value: "All", label: "All" }]
    );
}}
An All option is now present in our Select widget’s list of options.
  • Sort your data with _orderBy.

Snippet used

{{
    _.orderBy(
      _.union(
        _.uniqWith(fetch_events.data.map((i) => i.sport)).map(
          (i) => ({
            label: i,
            value: i,
          }),
          _.isEqual
        ),
        [{ value: "All", label: "All" }]
      ),
      ["label"],
      ["desc"]
    );
}}
We automatically sort the filtered data alphabetically.

Moment to moment

When working with dates and times, moment comes handy. For example, you can use moment.js to show the countdown between two dates or converting dates into required formats.

Here’s a Moment.js cheatsheet to keep handy.

Snippet used

The next Olympics starts on Friday, 26 July 2024 (Countdown--
{{function(){ 	// convert dates into required formats
	let today = moment().format("LL"); 	let next_olympics= moment("Friday, 26 July, 2024")
	return next_olympics.diff(today, 'days');
}()}} -  days)

JST We use moment.js to show when the next Olympics start.

6️⃣ Today, Appsmith supports six external libraries. Learn more.

Extend code functionality

For conditional navigation to another page in your app, opening and closing interactive elements like modals, showing alerts, and storing the value of a variable for dependent use later, Appsmith offers Actions in JS Objects.

➡️ Ten action methods with the Appsmith framework will make it easy for you to write better code within your application. Read about Actions on docs here.

Store it

  • Store any value within your application's local session store using the storeValue function.

Snippet used

{{
    storeValue("selected_year", filter_year.selectedOptionValue).then(() => {
      showAlert("Saved selected to local store");
    });
}}
We store the year selected so we can use it later for a chart. The JS Object also includes a showAlert function to inform the selected year was stored successfully.

Trigger routes

  • Switch between pages using the navigateTo action referencing a JS Object…

Snippet used

{{

storeValue("selected_year", filter_year.selectedOptionValue).then(() => {
	navigateTo('Page2', 'SAME_WINDOW')	
		})
}}
  • …or just between tabs.

Snippet used

{{ storeValue("selected_year", filter_year.selectedOptionValue).then(() => {
	storeValue("selected_tab", "Analyse by year")
		})
}}

We get to a page where we will build our chart.

Write clean code

JavaScript toggles in widget props and in queries are great, but sometimes, you need to reference longer JavaScript code. JS Objects on Appsmith offer you a modern JavaScript Editor experience for writing your JavaScript functions more cleanly and efficiently.

Declare reusable functions and variables

To avoid referencing variables over and over in your queries, you can just write a JS Object with functions and variables, then reference the Object in your queries.

  • For queries that need to run in sequence, a JS Object helps write cleaner dependencies and asynchronous functions.

Snippet used

onSeasonChange: async () => {
		return fetch_years.run().then(() => {
			return fetch_events.run();
		})
			.then(() => {
			return fetch_athelets_with_filters.run();
		});
	}

Selecting “Winter” updates the values in the adjacent filters relative to the season.

  • Use async and await inside JS Objects to enable promise-based asynchronous workflows.

Snippet used

refresh: async () => {
		await fetch_seasons.run()
		await fetch_years.run();
	         await fetch_events.run();
		await fetch_athelets_with_filters.run(); }
Our default season is “Summer”, so each time we hit the Refresh button, the JS Object first sets the default season to Summer, and then sets default values for the Year and Sports filters.

Chart it out

If you are already familiar with Appsmith Charts and data bindings to them, you can use JS Objects to configure your chart axes, labels, and data fields, then reference it directly within the chart widget’s props with something like{{chart_manager.events_by_sports()}}.

Snippet used

events_by_sports: () => {
		// bring data from query
		const data = chart_event.data;
		const dataSource = {
			
			// fusion chart configuration for customizing charts
			chart: {
				xaxisname: "Sport",
				yaxisname: "Number of events",
				palettecolors: "#818cf8",
				theme: "fusion"
			}, 			// query transformations with .map()
			data: data.map(e => ({
				label: e.sport,
				value: e.event
			}))
		};
		return (
			{
				// chart type and configuration
				type: "column2d",
				dataFormat: "json",
				dataSource
			}
		);
	},
The year selected in storeValue is used to show the number of events by sport on a pretty chart. ❤️

Final touches

To add a pinch of personality to your app, you can use JavaScript in Text or other widgets’ props to show data from public APIs, another database, or even SaaS tools like Slack and Notion.

Our fun snippet at the bottom is a really fun use of JavaScript and is coded as Did you know, in {{year_filter.selectedOptionValue}}, a whopping {{chart_event.data[0].event}} events were conducted in {{chart_event.data[0].sport}}?.