The DevXP engineering team hosts office hours every Thursday at 11 a.m. Pacific Time where we answer your questions live and help you get up and running with Flatfile. Join us!

Flatfile can support the simplest of workflows to the most nuanced & complex with Dynamic Spaces.

Use cases

The use cases for dynamic configuration are endless, here are just a few ideas:

  • Perhaps the user who is creating the Space informs how you want that Space to look for them
  • Or maybe someone’s location defines a different type of currency in your Sheet configuration
  • Or say you need data from an external API in a precise moment in time to determine how you want your Workbook to look

Continue reading to learn how to configure a Space from scratch, and update it as things change.

Configuring a new Space

From the dashboard

When the “Create New Space” button is clicked on the platform, it triggers a job event within the space domain that initiates a configure operation. This operation is analogous to performing a POST request to the endpoint /api/v1/spaces with the parameter autoconfigure set to true.

  1. Filter on the domain (space) and the operation (configure).
  2. Listen for a job:ready event.
  3. Build your Space, at minimum including one Workbook.
  4. Complete the job.
  5. Optionally, listen for new events that are spawned from within your space:configure job.

Usage

In the following example, we build a Workbook and our getting started guide. You can also follow along in the flatfile-docs-kitchen-sink Github sandbox.

Be sure to complete the job when it’s complete. This tells the platform that you’re finished and ready to display the Space to the end user.

import api from "@flatfile/api";
import { configureSpace } from "@flatfile/plugin-space-configure";

export default function (listener) {
  listener.use(
    configureSpace(
      {
        workbooks: [
          {
            name: "All Data",
            labels: ["pinned"],
            sheets: [
              {
                name: "Contacts",
                slug: "contacts",
                fields: [
                  {
                    key: "firstName",
                    type: "string",
                    label: "First Name",
                  },
                  {
                    key: "lastName",
                    type: "string",
                    label: "Last Name",
                  },
                  {
                    key: "email",
                    type: "string",
                    label: "Email",
                  },
                ],
                actions: [
                  {
                    operation: "sendToPeople",
                    mode: "background",
                    label: "Send to selected People",
                    description: "Send this data to those selected.",
                    constraints: [{ type: "hasSelection" }],
                  },
                ],
              },
              {
                name: "Sheet 2",
                slug: "sheet2",
                fields: [
                  {
                    key: "firstName",
                    type: "string",
                    label: "First Name",
                  },
                  {
                    key: "lastName",
                    type: "string",
                    label: "Last Name",
                  },
                  {
                    key: "email",
                    type: "string",
                    label: "Email",
                  },
                ],
              },
            ],
            actions: [
              {
                operation: "submitActionFg",
                mode: "foreground",
                label: "Submit foreground",
                description: "Submit data to webhook.site",
                primary: true,
              },
            ],
          },
        ],
      },
      async (event, workbookIds, tick) => {
        const { spaceId } = event.context;
        await api.documents.create(spaceId, {
          title: "Getting Started",
          body:
            "# Welcome\n" +
            "### Say hello to your first customer Space in the new Flatfile!\n" +
            "Let's begin by first getting acquainted with what you're seeing in your Space initially.\n" +
            "---\n",
        });
        await tick(80, "Document created");
      }
    )
  );
}

// See full code example (https://github.com/FlatFilers/flatfile-docs-kitchen-sink/blob/main/javascript/dynamic-configurations/index.js)

See full code example in our flatfile-docs-kitchen-sink Github repo

From an embedded button

When embedding Flatfile in your application, two things can happen:

  1. A new Space is created every time the Flatfile platform is called to open
  2. Or an existing Space can be passed in.

Listeners can be set up either server-side (use this Guide) and/or client-side within the embedded wrapper SDK.

Learn more about this use case.

Automatically

New Spaces can be created automatically by setting up headless flows.

Learn more about this use case.


Updating a Space in place

As things are changing in a Space, sometimes you may want to adjust the configuration of your Space. You can do this by listening for events that take place, and performing work as a result.

Continue reading for a few common examples.

After an action is fired

When a button is clicked in the user interface, this creates a job. You are already listening for this job to respond and do the work of that Action; however, you may also want to adjust some of your configuration at the same time, too.

Usage

In the following example, we lock down access to the original Sheet and update our getting started guide to reflect the change.

import api from "@flatfile/api";

export default function (listener) {
  listener.on(
    "job:ready",
    { job: "workbook:submitActionFg" },
    async ({ context: { jobId } }) => {
      try {
        await api.jobs.ack(jobId, {
          info: "Gettin started.",
          progress: 10,
        });

        //make changes after cells in a Sheet have been updated
        console.log("make changes here when an action is clicked");

        await api.jobs.complete(jobId, {
          outcome: {
            message: "This job is now complete.",
          },
        });
      } catch (error) {
        console.error("Error:", error.stack);

        await api.jobs.fail(jobId, {
          outcome: {
            message: "This job encountered an error.",
          },
        });
      }
    }
  );
}

See full code example in our flatfile-docs-kitchen-sink Github repo

After data changes

As the Sheet is being updated with data, perhaps you want to change the configuration. In the following example, we listed for a commit created to do just that.

Usage

listener.on("commit:created", { sheet: "Contacts" }, async (event) => {
  //make changes after cells in a Sheet have been updated
});
// See full code example (https://github.com/FlatFilers/flatfile-docs-kitchen-sink/blob/main/javascript/dynamic-configurations/index.js)

See full code example in our flatfile-docs-kitchen-sink Github repo

Example Project

Find the dynamic-configurations example in the Flatfile GitHub repository.