Forms

A part of the ShipEngine Connect platform is allowing integrations to define their own forms used for things like registering or connecting a new account. These forms are defined using the react-jsonschema-form syntax, and are comprised of two parts, a JsonSchema and a UiSchema.

Example

Pro Tip

By adding the "ui:order" property to your UiSchema you can gaurantee the order that the form fields will be generated in. Due to serialization / deserialization we cannot gaurantee order of form fields without this property.

form
registration-form.tscarrier.ts
Copy
Copied
const JsonSchema =  {
    type: "object",
    title: "Login Form Example",
    required: ["email", "password"],
    properties: {
    email: {
        type: "string",
        title: "Email Address",
        format: "email",
    },
    password: {
        type: "string",
        title: "Password",
        minLength: 8,
    },
    },
    description: "Connect to your account.",
};

const UiSchema = {
    "ui:order": ["email", "password"],
    email: {
    "ui:autofocus": true,
    "ui:emptyValue": "you@example.com",
    },
    password: {
    "ui:help": "Note: password is case sensitive",
    "ui:widget": "password",
    },
};

export const RegistrationFormSchema = {
    JsonSchema,
    UiSchema,
};
Copy
Copied
import {
  Carrier
  ...
} from "@shipengine/connect-carrier-api";
import { RegistrationFormSchema } from "./registration-form";
import { SettingsFormSchema } from "./settings-form";


export const DemoCarrier: Carrier = {
 ...
  AccountModals: {
    RegistrationFormSchema,
    SettingsFormSchema
  },
};

Learning More

You can learn more by visiting the official react-jsonschema-form website, or by playing with their interactive playground.

Handling input in the Register method

If you are building a Carrier app, you must implement a Register method to process the user input when a connection is created. Other types of apps do not currently support the Register method, however, all of the user input from the registration form is included in the auth part of the input in every function call to your app.

Given the following definition for the JsonSchema

Copy
Copied
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string"
    },
    "password": {
      "type": "string"
    },
    "CaseSensitive": {
      "type": "boolean"
    }
  }
}

When the "Connect" button is clicked by a user the Register Method would receive a payload looking something like this:

Request Payloadregister.ts
Copy
Copied
{
    "registration_info": {
        "email": "test@example.com",
        "password": "password",
        "CaseSensitive": true
    },
    "transaction_id": "fa4525b2-8dd2-4514-acf5-5c92173d31fd",
    "metadata": {
    }
}
Copy
Copied
...
interface RegistrationForm {
    email?: string;
    password?: string;
    CaseSensitive?: boolean;
}

export const Register = async (request: RegisterRequest): Promise<RegisterResponse> => {
    const { 
        email,
        password,
        CaseSensitive
    } = request.registration_info as RegistrationForm;
    ...
}
Notice

Notice how the interface for the RegistrationForm in the typescript code defined every field as being potentially null given the ?. This is because we did not mark any of these fields as required in our JsonSchema.