4
October
2022
Announcement

Appsmith Hacktoberfest - Week 1 Theme and Free Coins

0
 minutes

At Appsmith, we like to do things a bit differently, and Hacktoberfest is no different. While we are looking for submissions all month, we will be announcing the 4 themes for the template contest each week. 

Additionally, we will have a way *each* week to get “free” coins, which can be redeemed for prizes in our swag store! Check back each week to find out how to get these free prizes.

Themes and prizes - how it works

In order to encourage a broad range of submissions from a broad range of people, we have arranged the template contest across 4 themes:

  1. Startup apps
  2. UI Kits and Designs
  3. App clones
  4. Dashboards

For each theme, we will have 3 categories:

  1. Best UI
  2. Clever Use of Code
  3. Most Inspirational

And, in each category, we will have 3 prizes:

  1. Gold - 10 coins
  2. Silver - 7 coins
  3. Bronze - 4 coins

A bit of multiplication (4 x 3 x 3) will reveal that we are giving out 36 prizes in total! Even better, all accepted submissions may be added to our community repository. So, not only can you win cool stuff, but you also may have your contribution immortalized in our community library. It’s a win-win scenario.

Theme 1 - Startup apps

For the first theme, we want to focus on “Startup Apps”. In other words, we want to see cool, clever, and amazing apps that any new startup would find useful. Whether the startup is a pre-seed project being run out of a garage or is a Series B+ funded organization with millions to wisely spend.

All businesses need internal applications, and often you can see smaller organizations struggling to scale by trying to build or buy solutions to help them manage their growing business and team. 

Appsmith makes this easier by allowing them to quickly build and implement internal apps as fast as they can be imagined, planned, and outlined. We can make it even easier by sharing community application templates that can inspire or provide a great starting point.

Who knows, the Startup App that you submit could be the thing that helps the next great open source company survive and thrive! It will at least be a great example of how people can use Appsmith to move faster and leverage the power of open source to do well.

Free coins

While we hope that everyone contributes great stuff, and we would love to give everyone a prize, that's just not how it works. We have tried to find a balance between offering great prizes and giving awards to as many people as possible.

But, there is a bit of a loophole. 

Each week, we will have a “mini-quest” that you can complete to win a free coin for our shop! All you have to do is visit our Hacktoberfest app, and click on the “Coins” menu item. Here, we will have a new quest each week that you can perform and redeem in order to win a bonus coin!

The only caveat is that you need to be registered to take part, AND you need to go check out the mini-quest each week. You should have plenty of time to do that in between writing code and building templates!

So - what is the week 1 mini-quest? It’s almost TOO EASY! All you have to do is register in our Hacktoberfest App and then visit the Coin page to redeem your coins. That's it - I told you it was too easy.

FAQ Week 1

  • Do I need to wait for the weekly theme announcement to submit something?
    No way! You can submit code or templates anytime in October, for any theme. We will talk more about them each week, but if you have a great idea, start today!

  • Do I need to have a Github account to participate?
    Yes, you do. Our main code repository and our community library both live on Github, so we will need you to have a Github account.

  • What are these “coins” and why do I want them?
    A coin is a virtual currency that can only be spent in our Swag Shop (coming soon). Trust us - you will want coins so you can get some of our great swag!

  • Instead of templates, can I just submit good old-fashioned code for Hacktoberfest?
    Of course! We have a convenient listing of Hacktoberfest issues in our app for you to contribute to. Go ahead and get registered, and then get coding.

  • Can I submit to issues AND the template contest? Is that legal?
    Let me check the rules… hmmm…. not seeing anything that prevents that, so go for it! In fact, there isn’t anything in the rules preventing you from submitting code and winning multiple template prizes. The more you play, the more likely you are to win.

  • So, can I get enough coins to buy everything in the store?
    I don’t know… can you? 

Appsmith Hacktoberfest - Week 1 Theme and Free Coins

Share this

At Appsmith, we like to do things a bit differently, and Hacktoberfest is no different. While we are looking for submissions all month, we will be announcing the 4 themes for the template contest each week. 

Additionally, we will have a way *each* week to get “free” coins, which can be redeemed for prizes in our swag store! Check back each week to find out how to get these free prizes.

Themes and prizes - how it works

In order to encourage a broad range of submissions from a broad range of people, we have arranged the template contest across 4 themes:

  1. Startup apps
  2. UI Kits and Designs
  3. App clones
  4. Dashboards

For each theme, we will have 3 categories:

  1. Best UI
  2. Clever Use of Code
  3. Most Inspirational

And, in each category, we will have 3 prizes:

  1. Gold - 10 coins
  2. Silver - 7 coins
  3. Bronze - 4 coins

A bit of multiplication (4 x 3 x 3) will reveal that we are giving out 36 prizes in total! Even better, all accepted submissions may be added to our community repository. So, not only can you win cool stuff, but you also may have your contribution immortalized in our community library. It’s a win-win scenario.

Theme 1 - Startup apps

For the first theme, we want to focus on “Startup Apps”. In other words, we want to see cool, clever, and amazing apps that any new startup would find useful. Whether the startup is a pre-seed project being run out of a garage or is a Series B+ funded organization with millions to wisely spend.

All businesses need internal applications, and often you can see smaller organizations struggling to scale by trying to build or buy solutions to help them manage their growing business and team. 

Appsmith makes this easier by allowing them to quickly build and implement internal apps as fast as they can be imagined, planned, and outlined. We can make it even easier by sharing community application templates that can inspire or provide a great starting point.

Who knows, the Startup App that you submit could be the thing that helps the next great open source company survive and thrive! It will at least be a great example of how people can use Appsmith to move faster and leverage the power of open source to do well.

Free coins

While we hope that everyone contributes great stuff, and we would love to give everyone a prize, that's just not how it works. We have tried to find a balance between offering great prizes and giving awards to as many people as possible.

But, there is a bit of a loophole. 

Each week, we will have a “mini-quest” that you can complete to win a free coin for our shop! All you have to do is visit our Hacktoberfest app, and click on the “Coins” menu item. Here, we will have a new quest each week that you can perform and redeem in order to win a bonus coin!

The only caveat is that you need to be registered to take part, AND you need to go check out the mini-quest each week. You should have plenty of time to do that in between writing code and building templates!

So - what is the week 1 mini-quest? It’s almost TOO EASY! All you have to do is register in our Hacktoberfest App and then visit the Coin page to redeem your coins. That's it - I told you it was too easy.

FAQ Week 1

  • Do I need to wait for the weekly theme announcement to submit something?
    No way! You can submit code or templates anytime in October, for any theme. We will talk more about them each week, but if you have a great idea, start today!

  • Do I need to have a Github account to participate?
    Yes, you do. Our main code repository and our community library both live on Github, so we will need you to have a Github account.

  • What are these “coins” and why do I want them?
    A coin is a virtual currency that can only be spent in our Swag Shop (coming soon). Trust us - you will want coins so you can get some of our great swag!

  • Instead of templates, can I just submit good old-fashioned code for Hacktoberfest?
    Of course! We have a convenient listing of Hacktoberfest issues in our app for you to contribute to. Go ahead and get registered, and then get coding.

  • Can I submit to issues AND the template contest? Is that legal?
    Let me check the rules… hmmm…. not seeing anything that prevents that, so go for it! In fact, there isn’t anything in the rules preventing you from submitting code and winning multiple template prizes. The more you play, the more likely you are to win.

  • So, can I get enough coins to buy everything in the store?
    I don’t know… can you? 

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

  • xvcmbmvkmnkmbknmbkmlnj
  • A rich text element can be used with static or dynamic content. For static content, just drop it

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

  1. A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

ksnopirirfnb [aorewmb[oiewsn b[opebr
  1. then connect a rich text

dfbstjsrykmsry

Square
Try Appsmith
How to build a GitHub issues dashboard in thirty minutes or less
26
October
2022
Tutorial

How to build a GitHub issues dashboard in thirty minutes or less

How to build a GitHub issues dashboard in thirty minutes or less
Joseph Petty
0
 minutes ↗
#
graphql
#
github
Tutorial

GitHub Insights provides totals on issues and pull requests including links to  individual issues and PRs. You can filter by the last day, three days, a week or a month. It’s like a dashboard overview of your GitHub repository.

GitHub_dashboard__Appsmith.jpg (1920×1080)

While this is useful, it lacks a few key features.

  • It can’t have customized views for insights unique to you and your team.
  • It doesn’t drill-down into sub-categories of like issues by type or most popular issues by the number of comments.

To get around, this two-part post will show how to build a custom dashboard for your team and repos using GitHub’s GraphQL endpoints and native-GraphQL support in Appsmith.

Sign up to build your own GitHub insights dashboard

What this part covers

In two words, GraphQL and JavaScript. You will see how to:

  • Enable GitHub’s GraphQL API for your repo and create an access token
  • Build queries with the GitHub GraphQL explorer
  • Use GraphQL query variables
  • Use the authenticated GraphQL API in Appsmith
  • Present the response data on a dashboard

  • Use the Array map() method in JavaScript

Enabling the GitHub API

From your GitHub apps settings,

  1. Select Personal Access Token, and then Generate a new token.
  1. Add a note, set an expiration date, and select the scopes you want to enable. For our dashboard, we’ve left all the write scopes unchecked because the dashboard is read-only.
  1. Click Generate Token and then copy and save the token somewhere safe. You won’t be able to access it again from GitHub.
GitHub_apps_settings__Appsmith.jpg (1920×1080)

Building queries with the GitHub GraphQL explorer

  1. Start by logging into the Explorer to access the GraphQL API. You should see a default query already entered. Run it to make sure the Explorer can access your GitHub account.
GitHub_GraphQL_explorer.jpg (1920×1080)

{
  "data": {
    "viewer": {
      "login": "YOUR_GITHUB_LOGIN"
    }
  }
}

You should get back a response with your GitHub username.

  • Click the Explorer button next to show the left sidebar, then build a new query to get a few top level stats about your repo. Just go through the >repository node and select any fields you want to include in the dashboard.
  1. Type in the name of the repository and the owner name, then run the query.

{
  viewer {
    login
  }
  repository(name : "appsmith", owner : "appsmithorg") {
    id
    description
    homepageUrl
    stargazerCount
    issues {
      totalCount
    }
  }
}

You should see the totalCount populate as a run-time response for the query.
  1. You now have the totalCount of issues but not the breakdown by Open and Closed. While these would be two different queries in the REST API world, GraphQL lets you use aliases in one query to get subsets of the overall data.
Nice!

GraphQL query variables

  1. Instead of hard coding the repo name and owner, you can use query variables from the QUERY VARIABLES pane as an object.

{
  "owner": "appsmithorg",
  "repo": "appsmith"
}

  1. You would then add the variables to the original query.

query MyQuery($repo:String!,$owner:String!) {
  repository(name: $repo, owner: $owner) {
    issuesOpen:issues(states: OPEN) {
      totalCount
    }
    issuesClosed:issues(states: CLOSED) {
      totalCount
    }
  }
}

  1. Go through the rest of the >repository node of the Explorer and add any other fields you’d like for your dashboard, using aliases where needed to get subtotals. The final result should look something like ↓.

query getOVerview($owner:String!, $repo:String!) {
	repository(name: $repo, owner: $owner) {
		id
		name
		owner {
			id
			login
		}
		description
		homepageUrl
		stargazerCount
		collaborators {
			totalCount
		}
		watchers {
			totalCount
		}
		forkCount
		diskUsage
		issues_open: issues(states: OPEN) {
			totalCount
		}
		issues_closed: issues(states: CLOSED) {
			totalCount
		}
		PRs_open: pullRequests(states: OPEN) {
			totalCount
		}
		PRs_merged: pullRequests(states: MERGED) {
			totalCount
		}
	}
}

  1. While you’re here, create one more query to get a list of repos for your GitHub Organization. This will be useful in offering a picklist of repo names to choose from later.

query {
  organization(login: "appsmithorg") {
    repositories(first: 100) {
      edges {
        node {
          name
        }
      }
    } 
  }
}

GitHubs_name_attribute_on_GraphQL_explorer__Appsmith.jpeg (1920×1080)

Connecting the GraphQL API in Appsmith

Now that you have your GraphQL API token and the queries for your dashboard, let’s set up an authenticated GraphQL API in Appsmith.

  1. Start a new app, then add a new datasource from the Explorer in the left nav.

URL: https://api.github.com/graphql

Authentication Type: Bearer Token

Bearer: {{value from GitHub}}

  • The Bearer Token value is they access token you generated on Github.
  1. Name and save the datasource.
  1. Add a new API to this datasource.
  1. Copy the query from GitHub’s GraphQL Explorer into the Body of the API.
  1. Copy the query variables from GitHub to the Query Variables pane.
  1. Run the API.
GitHub_GraphQL_query_response__Appsmith.jpg (1920×1080)
  1. Add one more API for the repo list, and copy over the query and variables from GitHub.
Alright! We have the API playing nice with Appsmith.

Presenting data in widgets

First add an Input Widget for the owner name.

💡 Smith’s tip

Give it a descriptive name you can reference uniquely later.

I prefer using a short prefix for the widget type, e.g., in (for input), followed by an underscore, and then a descriptive term for the data it presents, e.g., in_owner. When I dynamically need the text value in the widget, I can reference it with {{in_owner.text}} in queries, JS toggles on widget props, or JS Objects in Appsmith.

Next, add a Select Widget for the repository name. With this widget, the user’s input can be referenced as {{in_repo.selecteOptionValue}}.

  1. The Select Widget requires an array of key-value pairs denoted label and value to supply the picklist’s options. If you look closer at the API response, you see a list of repo names but the data isn’t structured for this widget yet.
GitHub_GraphQL_repo_list_data_isnt_structured_for_Select__Appsmith.jpg (1920×1080)

Enter JavaScript

  1. First, let’s map over the edges and return an array of the nodes.
.map()_to_get_the_nodes_in_key-value_pairs__Appsmith.jpg (1920×1080)
  1. Then map over the nodes array to return the {label, value} array expected by the Select Widget.

nodesToArray: ()=> {
		return getRepos.data.data.organization.repositories.edges.map(e=>e.node)
			.map(n=>({label:n.name,value:n.name}))
}

Neat!
  • This lets you bind the data to the Select widget so when the end-user selects a repo name from the picklist, the query to the API can automatically be triggered.
Binding_the_transformed_name_node_array_to_Select__Appsmith.jpg (1920×1080)
For the Default Selected Value, you can use [0].value to default it to the first option in the picklist which is the first option in the query response.
  1. In the Select widget’s properties, set the onOptionChange event to trigger the query run the the getOverview API automatically for each option selected.
onOptionChange_binding_on_Select__Appsmith.jpg (1920×1080)
  1. Edit the getOverview API query variables to reference the new widgets. You can also add a fallback value in case the input is blank.

{
  "owner": {{in_owner.text || 'appsmithorg'}},
  "repo": {{in_repo.selectedOptionValue || 'appsmith'}}
}

The ||, the symbol for the logical OR operator, is to declare a default if the repo name is blank.

  1. Next up? Choosing the right widget for the data returned by the API. This part needs some understanding of the data and its structure. Here’s what the query response looks like.

//getOverview.data:
{
  "data": {
    "repository": {
      "id": "MDEwOlJlcG9zaXRvcnkyNzU5OTM4ODU=",
      "name": "appsmith",
      "owner": {
        "id": "MDEyOk9yZ2FuaXphdGlvbjY3NjIwMjE4",
        "login": "appsmithorg"
      },
      "description": "Low code project to build admin panels, internal tools, and dashboards. Integrates with 15+ databases and any API.",
      "homepageUrl": "https://www.appsmith.com",
      "stargazerCount": 21504,
      "collaborators": {
        "totalCount": 113
      },
      "watchers": {
        "totalCount": 232
      },
      "forkCount": 1849,
      "diskUsage": 286069,
      "issues_open": {
        "totalCount": 2579
      },
      "issues_closed": {
        "totalCount": 7458
      },
      "PRs_open": {
        "totalCount": 87
      },
      "PRs_merged": {
        "totalCount": 5893
      }
    }
  }
}

One way could be having a widget for each data point but that could very easily get out of hand if you have hundreds of fields. We will keep the Appsmith spirit of easy and fast and choose something more thoughtful.

  1. Let’s try the Table
  1. How about a JSONForm?
Presenting_GitHub_GraphQL_data_on_a_JSONForm__Appsmith.jpeg (1920×1080)
Better, but the data is still spread out and it’s hard to see everything at once.

We need a pivot-table of the data, but the current JSON structure isn’t quite right for that. So, we'll transform the data on the fly.

More JavaScript

  1. Your dashboard building trip so far has been without code. To build the UI right for the data, though, you will need to enter coding territory and introduce this data to our good friend, JavaScript.

1. Object.keys()

  1. Instead of one horizontal row, what if we could have one column for the field names and one for the values? The new data format should look something like ↓.

[
  {
    "field_name": "id",
    "value": "MDEwOlJlcG9zaXRvcnkyNzU5OTM4ODU="
  },  
  {
    "field_name": "Name",
    "value": "appsmith"
  },
...
]

  1. Start with a function that returns a list of the fields, or properties, of the repository object.

objToRows: (obj=getOverview.data.data.repository) => {
		return Object.keys(obj)
	},

🧠 Use Object.keys(object) to return an array of property names from an object.

2. Reduce

Next, you will need to iterate over these properties and return a new row object for our pivot table. The end result should be an array of objects with two properties, one for the field name and one for the value.

Sounds like a job for the reduce method.

Start with an empty array and add a new object for each property in the Object.keys() array.


objToRows: (obj=getOverview.data.data.repository) => {
		return Object.keys(obj).reduce((acc, value) => acc.concat({ 'prop': value, 'value': obj[value]}), [])
	}

Populating_(obj)_with_reduce__Appsmith.jpg (1920×1080)
  1. Next up? Choosing the right widget for the data returned by the API. This part needs some understanding of the data and its structure. Here’s what the query response looks like.

Presenting this new and transformed data on the Table should look like ↓.

Presenting_GitHub_GraphQL_transformed_data_on_the_Table__Appsmith.jpeg (1920×1080)
Cleaner UI, easier to see everything at once, but it could use some formatting.
  1. Your header row is a column now—magic!—, so it should look better to format the first column differently.

☝🏾 Disabling search, filters, download, and pagination options will help clean up the UI further. You don’t need those options for your dashboard anyway.

totalCount_in_GitHub_GraphQL_data_attributes__Appsmith.jpg (1920×1080)
Not bad, but it could be better. You’re building a dashboard after all.

3. Ternary operators

Those nested totalCount fields are kinda ugly. It would be much better if each value in the value column showed only the count. Before you get to doing it dynamically, let’s walk through the logic in plain English first.

If the value in the value column is an object and it has only one property,  show only the value for that property.

Use typeof to see if the value is an object, then use Object.keys().length to see if there is only one property.

Code logic

if ( typeof value == 'object' && Object.keys(value).length==1 ) ...do something

If the value in the value column is an object and it has nested properties, you want to show only the value of the nested properties, else you want to return whatever value was already there.

Use a ternary operator for this logic.

Code logic


flattenValues: (rows=utils.objToRows()) => {
		rows.forEach(r=>r.value = typeof r.value == 'object' && Object.keys(r.value).length==1 ? r.value[Object.keys(r.value)[0]] : r.value  );
		return rows
	}

Query_response_after_a_ternary_transformation__Appsmith.jpg (1920×1080)
Looks nice, but what about on the Table?
Data_on_table_minust_tableCount_labels__Appsmith.jpg (1920×1080)
Et voila!
GraphQL’s claim to fame is a lot fewer API calls than REST. As you have seen so far, the dashboard for the repo of interest is a single API call. You can continue tweaking the request body to match the exact data you need for the UI to get all of it in a single API response.

For finishing touches, move the in_repo and in_owner widgets into a new container for the header and add a second container for the Table.

Final_looks_in_containers__Appsmith.jpg (1920×1080)

Finally, add a border color and a width of 1.5 to make it look nice.

Border_and_color_for_the_GitHub_GraphQL_dashboard_MVP.jpg (1920×1080)
This dashboard has legs. It will run and run.

So, you now have an access token from GitHub, a ready GraphQL endpoint plugged into Appsmith, JavaScript-transformed data, and a pretty decent UI for it. ! And we're not even 15 minutes in! 

In part two, you will build the Issues Dashboard with a breakdown of issues by type over a time period of your choice, get issues with the most comments, and more.

Stay tuned.

The Low-coders Guide To JavaScript
19
October
2022
Product

The Low-coders Guide To JavaScript

The Low-coders Guide To JavaScript
Apeksha
0
 minutes ↗
#
javascript
#
js
#
code
Product
Write quick, clean, powerful code to build functional and beautiful internal apps

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

Post_1.gif (854×480)
One small step in the code, one giant leap for your app

Assuming you have connected your database to Appsmith and have run a successful query like we have, you can now 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 an consequently, the widget. JavaScript methods, natively supported in Appsmith, help make this a breeze.

  • 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
      };
    });
}}

Post_2.jpg (1920×1080)
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";
      });;
}}

Post_3.jpg (1920×1080)
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, as we have seen so far, expects data in the Array<Object> 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
}))

}}

Post_4.gif (854×480)
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;
}()

CleanShot_2022-10-25_at_15.55.292x.png (3584×2082)

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;

Post_5.gif (854×480)
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.
Post_6_(1).gif (854×480)
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") ); }}
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; 

Post_8.jpg (1920×1080)
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.
Post_9.jpg (1920×1080)

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
      )
}}

Post_10.jpg (1920×1080)
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" }] ); }}
Post_11.jpg (1920×1080)
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"]
    );
}}

Post_12.jpg (1920×1080)
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.

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)
Post_13.jpg (1920×1080)
We use moment.js to show when the next Olympics start.
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 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");
    });
}}

Post_16.gif (854×480)
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.
  • 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") }) }}
Post_18.gif (854×480)

Writing clean code

JavaScript toggles in widget props and in queries are great, but sometimes, you need to reference longer JavaScript code when building your app. 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 and 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(); }); }
Post_14_(1).gif (854×480)
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(); }
Post_15.gif (854×480)
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

Assuming you are already familiar with Appsmith Charts and how to bind data 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
			}
		);
	},

Post_21_(1).gif (854×480)
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}}?.
Meet the Table: A React table for building internal apps in less than 30 minutes
7
October
2022
Product

Meet the Table: A React table for building internal apps in less than 30 minutes

Meet the Table: A React table for building internal apps in less than 30 minutes
Balaji Soundararajan
0
 minutes ↗
#
widgets
#
product
#
table
Product

The Table is one of our top widgets by usage. Even with 25% of our users sending us telemetry data today, it has been used more than 820,000 times since we launched it. 🤯

Built on React Table

There are several libraries for building React tables, including our favorite and the massively popular, the React Table. We like it so much we sponsor it and can’t thank Tanner enough for building it.

We built our Table on top of it to help build internal apps lightning fast with ready features to support most popular use cases—an admin panel, dashboards, monitoring apps, and more—with out-of-the-box support for styling, theming, and in-line editing.

Let’s get into it

This post tears the upgraded Table widget down to all its component features and how you can use them. While our example today is an admin panel for a MakerPad-clone on Postgres, you will see how to build an admin panel for any datasource or other apps like dashboards, portals, and even CMSes.

💡 Toolspace, our MakerPad-clone, is a discovery app for open-source projects built on Postgres and Django. The Appsmith admin panel runs CRUD operations to the Postgres database for categories, alternative projects, data, and users.

Present tabular data

The Appsmith Table is familiar with a few powerful differences right out of the gate to help you leapfrog over typical web table set-ups.

One binding to bring it all

Assuming you have already connected your datasource and set up get queries to fetch data, it takes one small change—a binding—your freshly dropped Table to present the data.

Post_A.gif (1024×576)

Easy views for your data

You can write JavaScript almost everywhere in Appsmith. This comes handy when you want to create a view of your data for your app. Extend your Table Data binding with something like ↓


{{
getAllProjects.data.map((item)=>{
			return {
				"id": item.id,
				"name":item.name,
				"slug":item.slug,
				"logo":item.image_url,
				"github_url": item.github
			}
		})
}}

and voila! Your Table now shows the view you want. Use the Table Data property to manipulate your views any time.

☝ For easier code editing, we recommend you write longer code in a JS Object and reference it in the Table Data property.

Data to Table to data

Data exists as text, images, videos, URLs, and others on your database. Easily map datatypes from your database from the Column Type property under each column’s settings. This mapping is also used to update your database, as you will see later in this post.

Post_B.gif (1024×576)
A link pointer appears on URLs, and the image URLs change to the actual logo. 😍

For binary state values in columns—true or false, really— the Checkbox or Switch column types make it easy and visual for your end-users.

👌🏽 The Table supports over ten column types, including interactive components like buttons and icons. We talk about them below.

All in the names

Your database may have column headers that aren’t the best for your users, e.g., github_url. Edit those headers right on the Table as you would a filename. Double-click, type in your preferred header, e.g., GitHub URL, for each column, and done.

Post_3_(1).gif (1024×576)
No changing bindings. No transformations for such a small change.

What’s the value

Sometimes, your data isn’t in a single-entry-per-cell format. In our example, the alternative_products column has several related items per tool, so the column shows up as [], indicating an array.

Computed Value under column settings for each column translates the value in one swift binding to show that number.


{{currentRow["alternative_products"].length}}

Post_D.gif (1024×576)
👉 Computed Value supports JavaScript methods and functions—all of them.

Peek-a-boo columns

Often, you find columns you need to build and run your app—e.g., slug, that end-users don’t need to see. One-click on the eye per column on the Property pane, and you are done making them invisible to your users.

👉 Scroll horizontally to find hidden columns after the last visible column when you are building your app. Your end-users don’t see them when you deploy the app, though.

Order, order

Rearranging columns to present information hierarchically to your end-users is just a simple drag-and-let-go thing under Columns on the Property pane.

Post_E.gif (1024×576)
We move Name, Description, and Logo to show-up first. Easy-peasy ✌️.

Prettify it

The Table recently got themed, so you can now choose a default or a custom theme for your admin panel and see the Table get a personality in one click.

Post_M.gif (1024×576)

Unlock higher degrees of personalization for pixel perfect matches to your brand guidelines.

  • Color cells by column values with conditional styling using single or nested conditions in JS toggles available under the Style tab inside column properties.
Post_13.gif (1024×576)

{{
function() {
  if (currentRow.alternative_products.length == 0) {
    return "#E87171";
  }
  if (currentRow.alternative_products.length == 1) {
    return "#84cc16";
  }
  if (currentRow.alternative_products.length > 1) {
    return "#3b82f6";
  }
}()
}}


  • Control row height—short, default, tall—, text size—small, medium, large, extra-large—, and text alignment—left, right, center, top,  bottom—by the number of items you want to show. No-code needed.
Post_N_(1).gif (1024×576)
  • Customize borders and shadows for the entire table for consistency with your brand styles.
Post_O.gif (1024×576)

Get your rows in a page

Showing all your rows in one endless scroll isn’t the best end-user experience and loading it is a chore for your browser.

Magically paginate your apps with two out-of-the-box methods in Appsmith.

  • The pageNo and pageSize properties simplify pagination out of the box for queries and APIs.
Post_F.gif (1024×576)
We just add a Tablename.pageNo param to the API. That’s it.

  • We just add a Tablename.pageNo param to the API. That’s it.
  • The response-URL method relies on server-side pagination and is simpler for endpoints that have paginated URLs.
Post_9.gif (1024×576)

Make your data accessible

Presenting the data isn’t enough, especially when you have more rows than the lines of code you have written so far in Appsmith.

The Table makes accessibility easy and delightful.

Wrap it up

Toggling the Cell Wrapping settling on under Column settings lets your end-users see long text and evaluated values of dynamic bindings without scrolling or double-click gimmicks.

Search for it

Tables in Appsmith come with pre-built Search for all your data, paginated or otherwise. Search runs automatically each time you enter or change a keyword in the Search box.

Easily configure it one of two ways.

  • Write a search query with keywords like  ilike or find depending on your database.

SELECT * FROM users WHERE name ilike '%{{Table1.searchText}}%'

  • Use query params dynamically with your API like ↓.

https://api.toolspace.dev/api/all-xyz/?search={{Table1.searchText}}}


Sort and filter

While sorting your data takes just clicking column names or headers, filters offer a little more power to you.

  • Select a column, add a filter condition, and done—just like a spreadsheet.
Post_G_(1).jpg (1920×1080)
  • Add AND,  OR conditions for advanced filtering—just like you would in an analytics tool.
Post_H_(1).jpg (1920×1080)

Get a good view

Build unique views for better data presentation with table properties and triggers.

Spreadsheet view -- Use tabs to display multiple tables or filtered views of your data.

Post_I_(1).gif (1440×810)

Details view -- Show detailed views of your data on off-table components like Modal, Input, and Text widgets.

  • onClick-trigger them with Buttons, Icons, or Menus in a column.
Post_J.gif (1024×576)
Each row can have a detailed view triggered by a button, icon, or menu.
  • Menu buttons are especially useful to nest both view and delete triggers in one component—good for when you want to let familiar end-users delete data easily.
Post_Q.gif (1024×576)
  • Nifty Appsmith-native properties like selectedRow, triggeredRow, and selectedRowIndex make it super easy for you to dynamically open details views and, as we’ll see later, even edit them when you swap out the Text widget for an Input widget.
Post_7.gif (1024×576)
  • Run update queries using buttons to perform edit operations.
Post_P.gif (1024×576)

Did we mention already you can set intervals for auto-data refresh? No? Well, ↓ is all it takes.


{{

// runs for every five seconds

setInterval(() => { 
	 getAllProjects.run()
}, 5000)
}}

Post_14.gif (1024×576)

Two-click data export

Exporting your table data is, like most things so far, an affair of clicks for two of the most popular types—CSV or Excel

Post_12.gif (1024×576)

Add-edit-delete your data

So far, we have built a pretty functional, pretty pretty data viewer. This last set of features turns a viewer into a full-blown admin panel.

  • Add to your data from views

Use a Modal + an Input widgets, triggered from a column type or a Button outside of the table to open a set of blank input fields that save data entered with an onClick trigger.

Post_U.gif (1440×810)
  • Edit from views

Remember the unique views you built for your data? Extend those views to make them editable with Input + Button widgets instead of the Text widget. All changes to your fields get updated with the Button’s onClick trigger binded to an update query.

Post_S.gif (1024×576)
  • Delete from the Menu

We configured a delete trigger in our Menus before. Let’s put that to good use.

Post_T.gif (1024×576)

And, drumroll, please, you have a full-blown admin panel in under half-an-hour! 🥳

But wait, what if…

Inline editing without inline code

…your awesome admin panel could let your end-users edit data like they would on a spreadsheet?

Inline editing does just that. With your query for updates to your datasource built, all you need is to,

  • make your columns editable, and
  • bind the query to the EditActions column type—shown as the onSave property.
Post_L.jpg (1920×1080)
  • Your users then just do ↓.

Where the Table’s going

The Table has come a long way since we launched it many, many release cycles ago. Little did we think it could potentially become a CRUD app builder on its own. Which it is quite nearly now. So, we are building more and more on the table ourselves and asking, “Can’t we really turn this into an end-to-end app builder?”

You are welcome to stay updated about our tries or even contribute, but don’t let either of those stop you from using the Table, say, for an admin panel to a directory or for powering a dashboard for multiple datatypes and sources or even a whole Support app like ours.

Go for it. Your seat at the Table is waiting.