Skip Navigation

ICustomFormsService

Allows creating user defined forms and menus in a declarative way.

ICustomFormsService complements IFormsService, which allows opening and prepopulating Sabre defined forms.

Usage

In order to be used, the ICustomFormsService has to be imported:

import { ICustomFormsService } from 'sabre-ngv-custom-forms/services/ICustomFormsService';

Once imported, it can be obtained in a standard way:

const service: ICustomFormsService = getService(ICustomFormsService);

The service provides two methods:

openForm(form: string | CustomForm, title?: string): Promise<CustomFormRs>;

openMenu(menu: string | CustomMenu, title?: string): Promise<string | null>;

These methods take as a parameter declarative definition of the form/menu and optionaly a title (when the first argument is a string).

Due to the type of the first parameter - it can be either a string in a defined format or a dedicated data object - the service provides two types of the API - text API (string) and structure API (data object). Both APIs can be used interchangeably, but the text API does not support all features that are available in structure API - it is a subset of structure API and is intended to simplify the creation of basic forms.

In case of encountering a problem while parsing the data, an error banner will be displayed and the error message will be logged into the console.

Note
Detailed information about the service, its usage, form field types, and the structure of the data objects are available in TypeScript API Documentation of sabre-ngv-custom-forms module.
Note
com.sabre.redapp.example3.web.custom.forms SDK sample project contains many examples of using the service and shows how to create menus and forms with all available features like field types, field validation, action buttons, styled text and layouts.

Forms API

Allows creation of user defined forms in a simple declarative way.

Basic form

By default all fields are of type text and are optional (filling the field is not mandatory to submit the form).

Labels are generated from the field IDs - each part of the camel-case ID is treated as a separate word in the label.

const data = {
  title: 'Passenger Data',
  fields: [
    {id: 'firstName'},
    {id: 'lastName'},
    {id: 'title'}
  ]
};
service.openForm(data);
Basic form
const data = 'firstName, lastName, title';
service.openForm(data, 'Passenger Data');

Structure API allows defining custom labels, which are not generated from the field IDs.

const data = {
  fields: [
    {id: 'title', label: 'Title/Prefix'}
  ]
};
service.openForm(data);
Basic form with custom label
-

Mandatory Fields

Fields can be marked as mandatory. Form cannot be submitted if mandatory fields are empty.

const data = {
  title: 'Passenger Data',
  fields: [
    {
      id: 'firstName',
      validation: {mandatory: true}
    },
    {
      id: 'lastName',
      validation: {mandatory: true}
    },
    {
      id: 'title',
      label: 'Title'
    }
  ]
};
service.openForm(data);
Form with mandatory fields
const data = 'firstName*, lastName*, title';
service.openForm(data, 'Passenger Data');

Advanced Field Validation

Content of the text fields can be validated with regular expressions.

Regular expressions validation can be used together with mandatory field validation.

Form cannot be submitted if there are validation errors.

Custom error message can be provided.

const data = {
  fields: [
    {
      id: 'email',
      validation: {
        mandatory: true,
        regex: '^\\w+@\\w+(\\.\\w+)+$',
        error: 'Provide a valid email address'
      }
    }
  ]
};
service.openForm(data);
Form with validation
-
Warning
Regex validation is performed only if a field has a value, empty fields are not validated.

Field Types

Different field types can be defined in JSON object or added as a dash-separated suffix to the field ID in the text API.

TEXT (default)

Options: desc, icon, placeholder

const data = {
  fields: [
    {id: 'name'}
  ]
};
Field - text
const data = 'name';

CHECKBOX

Options: desc

const data = {
  fields: [
    {id: 'longConnect', type: 'CHECKBOX'}
  ]
};
Field - checkbox
const data = 'longConnect-checkbox';

DATE

Options: desc, minDate, maxDate

const data = {
  fields: [
    {id: 'departureDate', type: 'DATE'}
  ]
};
Field - date
const data = 'departureDate-date';

DROPDOWN

Options: desc, icon

const data = {
  fields: [
    {
      id: 'cabin',
      type: 'DROPDOWN',
      items: [
        {label: 'Economic', id: 'eco'},
        {label: 'Business', id: 'bus'},
        {label: 'Premium', id: 'pre'}
      ]
    }
  ]
};
Field - dropdown
-

RADIO

Options: desc

const data = {
  fields: [
    {
      id: 'cabin',
      type: 'RADIO',
      items: [
        {label: 'Economic', id: 'eco'},
        {label: 'Business', id: 'bus'},
        {label: 'Premium', id: 'pre'}
      ]
    }
  ]
};
Field - radio
-

CODE

Options: desc, icon, placeholder, optionsLimit

const data = {
  fields: [
    {
      id: 'cabin',
      type: 'CODE',
      items: [
        {label: 'Economic', id: 'eco'},
        {label: 'Business', id: 'bus'},
        {label: 'Premium', id: 'pre'}
      ]
    }
  ]
};
Field - code
-

{Domain}[1]_CODE

Options: desc, icon, placeholder, optionsLimit


1. Domain enum can be found here: sabre-ngv-app/app/services/impl/encodeDecode/Domain
const data = {
  fields: [
    {id: 'destination', type: 'AIRPORT_CODE'}
  ]
};
Field - radio
const data = 'destination-airportCode'

PARAGRAPH

Options: icon

Check out the styling text section.

const data = {
  fields: [
    {
      id: 'p',
      type: 'PARAGRAPH',
      text: 'We are a *software* and *technology* company that **powers** the global travel industry.'
    }
  ]
};
Field - paragraph
-

SEPARATOR

const data = {
  fields: [
    {id: 'field1'},
    {id: 's', type: 'SEPARATOR'},
    {id: 'field2'}
  ]
};
Field - separator
const data = 'field1, -, field2';

Fields prepopulation

Structure API allows opening the forms with prepopulated fields by filling 'value' property in the the data object. Fields of all types with 'value' property can be prepopulated.

const data = {
  fields: [
    {id: 'name', value: 'Red'},
    {id: 'check', value: true, type: 'CHECKBOX'},
    {id: 'city', value: ['KRK'], type: 'AIRPORT_CODE'},
    {id: 'date', value: '13SEP2022', type: 'DATE'}
  ]
};
service.openForm(data);
Form with prepopulated fields
-

Action buttons

When the form is submitted, returned object contains action field which indicates which button was selected to close the form. By default OK and Cancel buttons are displayed which return ok and cancel actions. It is possible to define custom buttons with custom actions that will replace default buttons.

When custom buttons are defined it is mandatory that at least one ok or cancel action is still present. These are default actions that are used when a form is closed with X button, Esc key, or Ctrl+Enter keys. By default, Ctrl+Enter keys combination runs ok action, if it was not provided cancel action will be run.

Labels for actions are optional and if not provided are generated the same way as labels for form fields or menu items.

const data = {
  fields: [
    {id: 'name'}
  ],
  actions: [
    {id: 'cancel'},
    {id: 'back', label: 'Prev'},
    {id: 'ok', label: 'Next'}
  ]
};
service.openForm(data);
Form with custom buttons
-

Layouts

By default fields are layout on the form one be one in one column.

Custom layouts can be defined with CSS grid-template-areas. Layouts are based on IDs of the form fields. The given layout does not affect the tab order over the form.

const data = {
  fields: [
    {id: 'from'},
    {id: 'to'},
    {id: 'departure'},
    {id: 'comments'}
  ],
  layout: [
    'from      to',
    '.         departure',
    'comments  comments'
  ]
};
service.openForm(data);
Form with layout
-

Description

For each field for which there is a label, you can also define a field description. The field description is rendered as an icon to the right of the label (the description is visible when you hover over the icon).

const data = {
  fields: [
    {
      id: 'name',
      options: {
        desc: 'Name of the traveler'
      }
    },
    {
      id: 'birthDate',
      type: 'DATE',
      options: {
        desc: 'Date of birth of the traveler'
      }
    }
  ]
};
service.openForm(data);
Form with fields descriptions
-

Icons

For some of the fields (see Field Types section) it is possible to define an icon. The Font Awesome icon name is expected (e.g. "fa-cog"). Icons are rendered inside the HTML input, to the left of the text.

The icon is rendered differently for PARAGRAPH field and additionally it supports the icon styles used in banners: Info, Warning, Success, Error.

const data = {
  fields: [
    {
      id: 'warning',
      type: 'PARAGRAPH',
      text: 'Remember to give the full name of the traveler and not to use special characters.',
      options: {
        icon: 'Warning'
      }
    },
    {
      id: 'name',
      options: {
        icon: 'fa-user'
      }
    }
  ]
};
service.openForm(data);
Form with icons
-

Placeholders

For some of the input fields (see Field Types section) it is possible to define a placeholder. It specifies a short hint that describes the expected value of the field. This short hint is displayed in the input field before the user enters a value.

const data = {
  fields: [
    {
      id: 'from',
      type: 'AIRPORT_CODE',
      options: {
        icon: 'fa-plane',
        placeholder: 'Origin'
      }
    }
  ]
};
service.openForm(data);
Form with placeholder
-

Text styling

The paragraph field allows to style the text.

The following subset of Markdown Syntax is supported:

  • Strong (bold) - surround text with two asterisks (**)

  • Emphasis (italic) - surround text with single asterisk (*)

  • Code - surround text with single back-quote (`)

  • Code Block - surround text with three back-quotes (```)

  • Escape character \

Combination of above styles is supported.

Multiple lines can be defined in a paragraph, to start a new line enter \n character.

Continuous lines of text belong to the same paragraph, to start a new paragraph, leave a blank line between lines of text.

const data = {
  fields: [
    {
      id: 'txt',
      type: 'PARAGRAPH',
      text: '**This text is strong.**\n' +
        '*This text is emphasis.*\n' +
        '`This is code fragment.`\n' +
        '```# This is code block\n' +
        '{\n' +
        '   "firstName": "John"\n' +
        '   "lastName": "Smith"\n' +
        '}```\n\n' +
        'This paragraph is separated from the previous paragraph.\n\n' +
        '**This** paragraph shows *combination* of ***styles***.\n\n' +
        '\\*This paragraph \\*\\*shows\\*\\* usage of \\`escape\\` characters\\*.'
    },
  ]
};
service.openForm(data);
Form with styled text
-

Advanced Sample

const data = {
  title: 'Custom Form',
  fields: [
    {
      id: 'info',
      type: 'PARAGRAPH',
      text: 'Please provide all **mandatory** fields to perform air availability search.',
      options: {
        icon: 'Info'
      }
    },
    {
      id: 'dep',
      type: 'AIRPORT_CODE',
      label: 'From',
      value: ['KRK'],
      options: {
        icon: 'fa-plane',
        placeholder: 'Origin'
      },
      validation: {
        mandatory: true
      }
    },
    {
      id: 'dest',
      type: 'AIRPORT_CODE',
      label: 'To',
      options: {
        optionsLimit: 2,
        icon: 'fa-plane',
        placeholder: 'Destination'
      },
        validation: {
        mandatory: true
      }
    },
    {
      id: 'date',
      type: 'DATE',
      label: 'Departure Date',
      options: {
        minDate: '13SEP2022'
      },
      validation: {
        mandatory: true
      }
    },
      {
      id: 'only',
      type: 'CHECKBOX',
      label: 'Direct Connection'
    },
    {
      id: 'sep',
      type: 'SEPARATOR'
    },
    {
      id: 'comm',
      type: 'TEXT',
      label: 'Other',
      options: {
        icon: 'fa-comment-o',
        desc: 'Additional information'
      }
    }
  ],
  layout: [
    'info  info',
    'dep   dest',
    'date  only',
    'sep   sep',
    'comm  comm'
  ]
};
service.openForm(data);
Form

Menus API

Allows creation of user defined menus in a simple declarative way.

Labels, if not provided, are generated from the ID the same way as in forms - each part of the camel-case ID is treated as a separate word in the label.

Structure API allows custom labels for menu items.

openMenu method returns ID of the selected item or null if menu is closed without any selection, e.g. with X button or with Esc key.

Menus may contain items of types:

  • MENUITEM - default type for menu

  • SEPARATOR - used for visually divide menu items, cannot be selected

const data =  {
  title: 'Sample Menu',
  items: [
    {id: 'airShopping', label: 'Air Shopping'},
    {id: 'airAvailability'},
    {id: 'airSchedules'},
    {id: 'sep', type: 'SEPARATOR'},
    {id: 'exit'}
  ]
}
const selectedId = service.openMenu(data);
Menu
const data = 'airShopping, airAvailability, airSchedules, -, exit';
const selectedId = service.openMenu(data, 'Sample Menu');