Getting Started

Hello World

Your first action script — from a one-line alert to a small form that answers back.

Every button in a TSQL.APP application runs an action script: plain T-SQL, stored as a row in the application's metadata. There is no front-end code to write. The script describes what the user should see by calling sp_api_* procedures, and the framework draws it.

One line

The smallest useful script shows a message and waits for the user to close it:

DECLARE @AlertText NVARCHAR(MAX) = N'Hello World';

EXEC sp_api_modal_alert @alert_text = @AlertText;

Add this as the SQL of a new action on any card, click the button, and an alert appears.

Notice that the text is put in a variable first, rather than passed as a literal expression. That is a habit worth keeping from the start: procedure parameters take values, not calculations, so anything you compute — a CONCAT, a FORMAT, a lookup — goes into a variable on the line before.

A form that answers back

The real shape of TSQL.APP code shows up as soon as the user types something. This script asks for a name and greets the user by it:

-- 1. Declare everything at the top
DECLARE @Name        NVARCHAR(MAX);
DECLARE @GreetButton NVARCHAR(MAX);
DECLARE @Greeting    NVARCHAR(MAX);

-- 2. Read what the user has entered so far
EXEC sp_api_modal_get_value @name = N'@Name',        @value = @Name OUT;
EXEC sp_api_modal_get_value @name = N'@GreetButton', @value = @GreetButton OUT;

-- 3. Draw the dialog
EXEC sp_api_modal_text   @text = N'Hello World', @class = N'h3';
EXEC sp_api_modal_input  @name = N'@Name', @value = @Name OUT, @placeholder = N'Your name';
EXEC sp_api_modal_button @name = N'@GreetButton', @value = N'Greet',
                         @valueout = @GreetButton OUT, @class = N'btn-primary';

-- 4. Nothing clicked yet: stop here and wait
IF @GreetButton IS NULL RETURN;

-- 5. Handle the click
IF LEN(TRIM(ISNULL(@Name, N''))) = 0
BEGIN
    SET @Greeting = N'Please enter your name first.';
    EXEC sp_api_toast @text = @Greeting, @class = N'bg-danger text-white';
    EXEC sp_api_modal_value @name = N'@GreetButton', @value = NULL;  -- un-click the button
    RETURN;
END

SET @Greeting = CONCAT(N'Hello, ', @Name, N'!');
EXEC sp_api_toast @text = @Greeting, @class = N'bg-success text-white';
EXEC sp_api_modal_clear;

What just happened

The script ran twice. The first time, nothing had been entered, so @GreetButton was NULL: the dialog was drawn and the script stopped at step 4. When the user clicked Greet, the browser sent the values back and the framework ran the whole script again from the top. This time sp_api_modal_get_value found a name and a clicked button, so step 5 ran.

That is the entire programming model of a dialog, and every guide here follows the same five steps:

  1. Declare all variables at the top.
  2. Synchronise state with sp_api_modal_get_value before drawing anything.
  3. Draw the controls — every run, not only the first.
  4. Pause with RETURN while there is nothing to do.
  5. Handle the action, and close the dialog with sp_api_modal_clear when finished.

Two details in step 5 matter more than they look:

The script being re-run from the top is not an implementation detail you can ignore — it is what makes a stateless web request feel like a conversation. The Inner Workings course explains the mechanism in full.