Use Retool and Fauna to build a Todo app

Application development with Fauna and Retool is easy with the Fauna GraphQL API. In this tutorial, you’ll build a Todo app using Fauna for data storage, a front end built with Retool, and GraphQL for querying and data manipulation.

Prerequisites

Set up a Fauna database

  1. Create a new database

    1. In the Fauna Dashboard, click the CREATE DATABASE link in the upper left corner.

    2. Name your database fauna-todo-db (or another name of your choice).

    3. In the Region Group dropdown menu, select Classic.

    4. Leave the Use demo data box unchecked.

    5. Click the CREATE button.

  2. Import a GraphQL schema for your database

    1. Using your preferred text editor, create a file named schema.gql with the following content:

      type Todo {
        title: String!
        completed: Boolean!
        list: List
      }
      
      type List {
        title: String!
        todos: [Todo] @relation
      }
      
      type Query {
        allTodos: [Todo!]
        todosByCompletedFlag(completed: Boolean!): [Todo!]
        allLists: [List!]
      }
    2. In the Fauna Dashboard, click GRAPHQL in the left-side navigation.

    3. Click IMPORT SCHEMA, which opens your browser’s file selector. Select the schema.gql file, and click the file selector’s Open button.

  3. Add some documents

    You can take a look at the results of the schema import by clicking DB OVERVIEW in the left-side navigation. You have two collections named Todo and List, but neither collection has any documents in it yet. The Todo collection is for individual todo items, and the List collection is for categories of todo items. We can add a new List document and several associated Todo documents with one GraphQL mutation:

    mutation CreateListWithTodos {
      createList(data: {
        title: "Chores",
          todos: {
            create: [
              {completed: false, title: "Walk the dog"},
              {completed: false, title: "Feed the cat"},
              {completed: false, title: "Buy milk"}
            ]
          },
      }) {
        _id
        title
        todos {
          data {
            title
          }
        }
      }
    }

    Paste the above mutation into your GraphQL Playground panel and click the "Play" button. Now if you go back and look at your collections again, you should see the results.

    For more information about using relations in a GraphQL schema, see the Relations tutorial.

    Before leaving the GraphQL Playground let’s run one more mutation, so there is more than one item in the List collection.

    mutation CreateListWithTodos {
      createList(data: {
        title: "Exercise Goals",
          todos: {
            create: [
              {completed: false, title: "Run 5 miles"},
              {completed: false, title: "Swim for 30 minutes"},
              {completed: false, title: "Bike to Fresno and back"}
            ]
          },
      }) {
        _id
        title
        todos {
          data {
            title
          }
        }
      }
    }
  4. Create an access key

    1. Click SECURITY in the left-side navigation.

    2. Click the NEW KEY button.

    3. Leave all the form inputs as they are and click the SAVE button.

    4. Your key’s secret is displayed. Copy it and save it for later use. Secrets are only ever displayed once. If you lose a secret, you have to create a new key.

Create a Retool application

Your Fauna database setup is complete, and now you’re ready to create a user interface for your Todo app. The Retool platform allows you to construct user interface elements which trigger GraphQL queries to your Fauna database, so you can add Todo items and mark them completed.

  1. Create a new Retool resource

    1. Log in to your Retool account. If you’re already logged in, navigate to your account home page by clicking the Retool icon in the upper left corner.

    2. On your Retool account home page, select RESOURCES from the top navigation.

    3. Click the CREATE NEW button.

    4. On the resource creation page, click the GRAPHQL button in the APIS section.

    5. Name the resource faunadbGQL (or another name of your choice).

    6. For the Base URL, enter https://graphql.fauna.com/graphql

    7. Leave the URL Parameters section blank.

    8. In the Headers section, enter the following keys and values:

      Key Value Notes

      Authorization

      Bearer <key secret for your database>

      Include your key secret here.

      Accept-Encoding

      gzip, deflate, br

      Specifies which compression algorithms the client can use.

      Content-Type

      application/json

      Specifies the media type of the resource.

      Accept

      application/json

      Specifies which media types the client can use.

      Connection

      keep-alive

      Specifies a persistent network connection.

    9. Leave the other fields unchanged.

      Retool Resource configuration

    10. Click TEST CONNECTION to validate your form entries. If the connection is successful, click CREATE RESOURCE, then CREATE AN APP.

    11. Name your app fauna-todo-app (or another name of your choice).

  2. Add a list table showing all items

    You should now see the main Retool app development workspace, where you can assemble the components for your Todo app.

    1. There may be a default table in your main app workspace named table1. To delete it, select the table and then select Delete from the action menu on the right side of the panel (next to the name table1).

    2. The bottom left section of your Retool workspace is where you can create and edit resource queries. Click the NEW dropdown menu and select Resource query.

    3. From the RESOURCE dropdown menu, select faunadbGQL (or the name of the resource you created earlier).

    4. In the Query box, add the following GraphQL query:

      query FindAllTodos {
        allTodos {
          data {
            _id
            title
            completed
            list {
              title
            }
          }
        }
      }

      The above query returns all the items in your Todo collection.

    5. Click the SAVE (sometimes Save and Run) button.

    6. Rename your new resource query allTodos.

    7. The right-side panel of your Retool workspace shows commonly used UI components. Drag a table into your main canvas. It is named table1 by default, and you can leave that name as it is.

      Retool insert table

    8. When the table is selected, the right-side panel shows its properties. Enter the following query reference in the Data input box:

      {{allTodos.data.allTodos}}

      All the Todo items currently in your collection should appear in the table, all in one big column. We’ll separate out the columns in the next step.

    9. With the table selected, look in the right-side panel for the Columns section. Click the CUSTOM COLUMN link three times, to give you a total of four columns.

    10. You can edit your new columns by clicking them to bring up their properties modal window. Edit the four columns to have the following properties:

      Column title Mapper/Calculation

      id

      {{currentRow.data._id}}

      Todo

      {{currentRow.data.title}}

      Completed?

      {{currentRow.data.completed}}

      Category

      {{currentRow.data.list.title}}

      Once your columns are defined you should see four columns in your table, listing your Todo items along with their ID, their category, and whether they’re completed or not.

      Retool Columns configuration

      Your table should now look something like this:

      Retool table

  3. Create a button for adding new Todo items

    Next, add a button which opens a modal window with a form for adding new Todo items. The form uses a GraphQL query to populate the list of categories, and then another query to add a document to your Todo collection.

    1. Click the INSERT link in the upper right corner to display the Components panel on the right side. Locate the UI element Modal and drag it to your canvas, above the table.

      In Retool, modal windows are attached to buttons by default, so you don’t need to add a separate button.
    2. With the modal’s button selected, use the Button text input box on the right side to rename the button to New Todo item.

    3. Clicking the new button brings up a canvas onto which you can add UI elements to the modal window. Drag a Form component onto the canvas.

      You can always bring back the components menu by clicking INSERT in the top right corner.
    4. Drag a Text input component onto the form canvas. Update its Label property to read New item.

      Retool insert modal

    5. Drag a Select component onto the form canvas below the text input.

      This select box will show a list of Todo item categories, so it needs a resource query.

    6. Down in the lower left corner, click the NEW dropdown menu and select Resource query.

    7. In the Query box, enter the following GraphQL query:

      query lists {
        allLists {
          data {
            _id
            title
          }
        }
      }
    8. Click SAVE and rename the new query listsDropdown.

    9. Edit the select1 form element to have the following properties:

      • Label: Category

      • Values: {{listsDropdown.data.allLists.data.map(val=>{return val._id})}}

      • Display values: {{listsDropdown.data.allLists.data.map(val=>{return val.title})}}

        Retool form canvas

    10. Now we need a query for the form’s Submit button to add a document to your Todo collection. Create a new resource query with the following GraphQL query:

      mutation CreateAListedTodo {
        createTodo(data: {
          title: "{{textInput1.value}}"
          completed: false
          list: {
            connect: "{{select1.value}}"
          }
        }) {
          title
          completed
          list {
            title
          }
        }
      }
    11. After this query runs, the list of items should refresh, so it needs an event handler. Below the query box, click the New link in the Event handlers section and add a new event handler with the following properties:

      • Event: Success

      • Action: Trigger query

      • Query: allTodos

    12. Save the new resource query and rename it createTodo.

    13. Now you can attach the new resource query to your form. Select the form and locate its event handlers on the right side. Add a new event handler and select createTodo from the Query dropdown menu.

    14. The button now works, but you need another event handler to make the modal window close after the form submits. Add a new event handler with the following properties:

      • Event: Submit

      • Action: Control component

      • Component: modal1

      • Method: Close

    15. You can drag and drop the form elements to reposition and reshape them, and then close the form canvas. Your NEW TODO button should now work, and you can try it out.

  4. Create a button to mark Todo items completed

    Next, you’ll add a button to mark individual Todo items as completed. First, create a new resource query to update a Todo item, then add a button to the main canvas.

    1. Create a new resource query with the following GraphQL mutation:

      mutation completeTodo {
        updateTodo(id: "{{table1.selectedRow.data.data._id}}",
          data: {
            title: "{{table1.selectedRow.data.data.title}}"
            completed: true
          }
        ){
          title
          completed
          list {
            title
          }
        }
      }
    2. Add an event handler to the new resource query with the following properties:

      • Event: Success

      • Action: Trigger query

      • Query: allTodos

    3. Save the new resource query and rename it to completeTodo.

    4. Back in your main canvas, drag a Button component next to the New Todo button.

    5. Edit the new button’s Text property to read Mark Completed.

    6. Add an event handler to the new button with the following properties:

      • Event: Click

      • Action: Trigger query

      • Query: completeTodo

    7. Set the button’s Disabled property to {{table1.selectedRow.data.data.completed}} so that it is grayed out when a completed item is selected.

At this point the app is functional, and you can click the PREVIEW button in the upper right corner to see how it looks in a web page. If you feel like you’ve grasped the basics you can stop here, or if you’d like to add more functionality to your app you can keep going.

Add more functionality

The Todo app works, but there’s one more feature we can add. In the following section you’ll add a switch to show only uncompleted items.

  1. Add an openTodos query

    Create a new resource query with the following GraphQL query:

    query openTodos {
      todosByCompletedFlag(completed: false) {
        data {
          _id
          title
          completed
          list {
            title
          }
        }
      }
    }

    Save the resource query and rename it openTodos.

  2. Add a switch to display only open items

    1. Drag a Switch component onto the main canvas. You can use the search box at the top of the Components panel to quickly locate a particular component. Rename switch to Display open only with the Label property.

    2. Add an event handler to the switch with the following properties:

      • Event: True

      • Action: Trigger query

      • Query: openTodos

    3. Add another event handler to the switch with the following properties:

      • Event: False

      • Action: Trigger query

      • Query: allTodos

    4. Update the table1 Data field

      To make the switch work, we need to make the main list table a bit smarter. Select the table1 component and update its Data property to the following:

      {{switch1.value ? openTodos.data.todosByCompletedFlag : allTodos.data.allTodos}}

    5. Update event handlers

      We need to update the event handlers for the createTodo and completeTodo resource queries. For each query replace the existing event handler with two new ones:

      Event handler 1:

      • Event: Success

      • Action: Trigger query

      • Query: allTodos

      • Only run when: {{!switch1.value}}

        Event handler 2:

      • Event: Success

      • Action: Trigger query

      • Query: openTodos

      • Only run when: {{switch1.value}}

        Save each resource query before closing.

    The Display open only switch is now functional.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!