Linking between actions
Just as you'd use <a>
tags to link between HTML pages, you can use Interval's linking APIs to let users navigate between pages and actions. For example, an action might link each row in a table to an "edit" action, or it could conditionally redirect from one action to another.
There are two components to a link: the action's slug, and an optional params
object.
Here's an example of two actions that link to each other:
- TypeScript
- JavaScript
- Python Experimental
src/routes/favorite_color.ts
// the path to this action is `favorite_color`
import { Action, io } from "@interval/sdk";
export default new Action(async () => {
await io.group([
io.display.markdown(`Choose your favorite color:`),
io.display.link("Blue", {
action: "result",
params: { favoriteColor: "blue" },
}),
io.display.link("Red", {
action: "result",
params: { favoriteColor: "red" },
}),
]);
});
src/routes/result.ts
// the path to this action is `result`
import { Action, ctx } from "@interval/sdk";
export default new Action(async () => {
await io.group([
io.display.markdown(`Favorite color is: ${ctx.params.favoriteColor}`),
io.display.link("Go back", {
action: "favorite_color",
}),
]);
});
src/routes/favorite_color.js
// the path to this action is `favorite_color`
const { Action, io } = require("@interval/sdk");
module.exports = new Action(async () => {
await io.group([
io.display.markdown(`Choose your favorite color:`),
io.display.link("Blue", {
action: "result",
params: { favoriteColor: "blue" },
}),
io.display.link("Red", {
action: "result",
params: { favoriteColor: "red" },
}),
]);
});
src/routes/result.js
// the path to this action is `result`
const { Action, ctx } = require("@interval/sdk");
module.exports = new Action(async () => {
await io.group([
io.display.markdown(`Favorite color is: ${ctx.params.favoriteColor}`),
io.display.link("Go back", {
action: "favorite_color",
}),
]);
});
import os
from interval_sdk import Interval, IO, ctx_var
interval = Interval(
os.environ["INTERVAL_API_KEY"],
)
# the path to this action is `favorite_color`
@interval.action
async def favorite_color(io: IO):
await io.group(
io.display.markdown("Choose your favorite color:"),
io.display.link(
"Blue",
route="result",
params={"favorite_color": "blue"},
),
io.display.link(
"Red",
route="result",
params={"favorite_color": "red"},
),
)
# the path to this action is `result`
@interval.action
async def result(io: IO):
ctx = ctx_var.get()
favorite_color = ctx.params["favorite_color"]
await io.group(
io.display.markdown(f"Favorite color is: {favorite_color}"),
io.display.link(
"Go back",
route="favorite_color",
),
)
interval.listen()
Linking within tables​
The most common use of links in Interval apps is to link to actions from within rows in display.table. Here's an example table that links to Edit & Delete actions for each row, and requires an id
param in order to run each of them:
- TypeScript
- JavaScript
- Python Experimental
src/routes/users/index.ts
import { Page, io } from "@interval/sdk";
import { getUsers } from "../../db";
export default new Page({
name: "Users",
handler: async () => {
const data = await getUsers();
await io.display.table("Users", {
data,
rowMenuItems: row => [
{
label: "Edit",
action: "edit_user",
params: { id: row.id },
},
{
label: "Delete",
theme: "danger",
action: "delete_user",
params: { id: row.id },
},
],
});
},
});
src/routes/users/edit_user.ts
import { Action, ctx } from "@interval/sdk";
import { getUser } from "../../db";
export default new Action(async () => {
if (!ctx.params.id) {
throw new Error("Missing required param: id");
}
const user = await getUser(ctx.params.id);
// ...
});
src/routes/users/delete_user.ts
import { Action, ctx } from "@interval/sdk";
import { getUser } from "../../db";
export default new Action(async () => {
if (!ctx.params.id) {
throw new Error("Missing required param: id");
}
const user = await getUser(ctx.params.id);
// ...
});
src/routes/users/index.js
const { Page, io } = require("@interval/sdk");
const { getUsers } = require("../../db");
module.exports = new Page({
name: "Users",
handler: async () => {
const data = await getUsers();
await io.display.table("Users", {
data,
rowMenuItems: row => [
{
label: "Edit",
action: "edit_user",
params: { id: row.id },
},
{
label: "Delete",
theme: "danger",
action: "delete_user",
params: { id: row.id },
},
],
});
},
});
src/routes/users/edit_user.js
const { Action, ctx } = require("@interval/sdk");
const { getUser } = require("../../db");
module.exports = new Action(async () => {
if (!ctx.params.id) {
throw new Error("Missing required param: id");
}
const user = await getUser(ctx.params.id);
// ...
});
src/routes/users/delete_user.js
const { Action, ctx } = require("@interval/sdk");
const { getUser } = require("../../db");
module.exports = new Action(async () => {
if (!ctx.params.id) {
throw new Error("Missing required param: id");
}
const user = await getUser(ctx.params.id);
// ...
});
import os
from interval_sdk import Interval, IO, ctx_var
import my_db
interval = Interval(
os.environ["INTERVAL_API_KEY"],
)
@interval.action
async def users(io: IO):
data = await my_db.get_users()
await io.display.table(
"Users",
data=data,
row_menu_items=lambda row: [
{
"label": "Edit",
"route": "edit_user",
"params": {"id": row["id"]},
},
{
"label": "Delete",
"theme": "danger",
"route": "delete_user",
"params": {"id": row["id"]},
},
],
)
@interval.action
async def edit_user(io: IO):
ctx = ctx_var.get()
user = await my_db.get_user(ctx.params["id"])
# ...
@interval.action
async def delete_user(io: IO):
ctx = ctx_var.get()
user = await my_db.get_user(ctx.params["id"])
# ...
interval.listen()
Was this section useful?