Suggested Approach?
I am trying to create a shortcut/script/automation that:
- calls and API
- displays the results in a similar way to a tableview (which has a couple action buttons on each row)
- when a button is selected continues on with the shortcut (or runs a different shortcut) passing the selected rows details.
Has anyone done anything similar or got any suggestions.
Hi!
- You can make API calls with
Request
- You can build a table in Scriptable with the
UITable
, UITableRow
and UITableCell
classes. Don’t forget to call table.present()
(where table
is the instance variable of the UITable
class) after you’re done building it to present it to the user.
- To make buttons use either
let btn = row.addButton("caption")
(where row is the UITableRow instance of the current row you are building) orlet btn = new UITableCell.button("caption")
row.addCell(btn)
and then assign your callback function to btn.onTap
.
In the callback function you can do whatever you like. If you want to run a shortcut useSafari.open("shortcuts://run-shortcut?name=" + encodeURIComponent("your shortcut name here") + "&input=" + "your data here in your favourite string format (base64, json, URL encoded,...)")
(If you want to transfer the word “clipboard” to shortcuts, you have to write "&input=text&text="
instead of "&input="
. It seems that this isn’t documented anywhere, but it was like that 2 years ago. If you don’t do it like that, shortcuts will use the contents of the clipboard as input)
An example table:
let table = new UITable();
// define contents of an example table
let data = [
["foo", "bar", "baz"],
["asdf", "quz", "42"],
[123, 567, "add"]
];
let row, cell;
let first = true;
for (const drow of data) { // drow = data row
// create a new row
row = new UITableRow();
// immediately add it to the table to not forget that part
table.addRow(row);
if (first) {
// set the first row to have bold text
row.isHeader = true;
first = false;
}
for (const [i, dcell] of drow.entries()) {
// the last cell should contain a button
if (i === 2) {
// cast dcell to a string, otherwise we will get an error like "Expected value of type UITableCell but got value of type null."
cell = row.addButton("" + dcell);
// even though the next line is not needed because it is the default setting, I like to do it anyway to be more specific of what is going on
cell.dismissOnTap = false;
// register our callback function
cell.onTap = () => {
// create a simple alert to have some user feedback on button tap
let alert = new Alert();
alert.message = dcell;
alert.present();
// no need to add buttons, they will be added automatically
// no need to await it, because we don't need anything from the user
};
} else {
// cast dcell to a string, otherwise we will get an error like "Expected value of type UITableCell but got value of type null."
cell = row.addText("" + dcell);
}
cell.centerAligned();
}
}
table.present();
I can’t give you more advice because that depends on your specific case.
Thank you so much for your detailed reply. I will take this a have a good at applying it all tomorrow. Can you tell me if you can do much styling to rows and cells etc?
According to the docs the only styling available is
- separators between rows (
UITable.showSeparators
)
- regular or bold font (
UITableRow.isHeader
)
- background color of each row
- height of each row
- space between the cells in one row (
UITableRow.cellSpacing
)
- relative width of cells (to each other in the same row:
UITableCell.widthWeight
)
- color of text (not buttons)
- alignment of cells
If you for example want a separator between multiple rows to create something like sections without showing separators between every row, you can set the background color of a row to black and it’s height to something small (like 2 or 3, just experiment with it).
If you need more styling options, then you can make the table in HTML with custom CSS and display that in a WebView
.