Сопоставление полей
Как ссылаться на значения предыдущих шагов с помощью выражений {{template}}.
Сопоставление полей
Почти каждому узлу нужны значения откуда-то ещё — из полезной нагрузки триггера, из выхода предыдущего действия, из вложенного поля на три уровня вниз в JSON-ответе. Сопоставление полей — это способ пробросить такие значения во входы узла.
В Triggo есть небольшой язык шаблонов вида {{source.path.to.value}}. Вы пишете такие выражения в любом текстовом поле инспектора; исполнитель разрешает их во время запуска, обращаясь к актуальным выходам узлов-предков.
Синтаксис
Разделитель — двойные фигурные скобки: {{... }}. Внутри — путь, разделённый точками. Реализация находится в.
Существуют два режима разрешения, выбираемые автоматически:
- Whole-value — всё поле ввода — это одно выражение, например
{{trigger.email}}. Разрешённое значение возвращается как есть, с сохранением типа. Число остаётся числом, массив — массивом, объект — объектом. - Inline — выражение встроено в большую строку, например
Hello {{trigger.name}}!. Каждое выражение разрешается и приводится к строке в окружающем тексте.nullиundefinedпревращаются в пустую строку.
Обращение к триггеру
Триггер особенный — у него зарезервированный корневой ключ:
{{trigger.field}}Под капотом исполнитель хранит выход каждого узла по его node ID. Когда вы пишете {{trigger...}}, резолвер сначала ищет буквальный ключ trigger, а если его нет, использует первый ключ, начинающийся с trigger (например, trigger_1). Это позволяет писать {{trigger.email}} независимо от того, как холст назвал узел триггера внутри себя.
Обращение к предыдущему шагу
Любой другой узел адресуется по его node ID — тому самому ID, который холст присваивает при добавлении узла:
{{action_1.id}}
{{http_request_2.body.status}}Откройте узел в инспекторе, чтобы увидеть его ID. Подборщик сопоставления полей в UI сам вставляет эти идентификаторы, так что вручную писать их приходится редко.
Обращение к вложенным значениям
Пути — это обычная точечная нотация. Каждый сегмент после корня трактуется как ключ объекта:
{{trigger.contact.email}}
{{action_1.customer.address.city}}Обход null-безопасен в том смысле, что возвращает undefined, как только любой сегмент отсутствует или не является объектом, — он не бросает исключение. См. traversePath в field-mapper.
Несколько вещей, которых нет в языке:
- Синтаксиса индекса массива. Нет
{{items.0.name}}или{{items[0].name}}. Резолвер делит путь по.и трактует каждый сегмент как ключ объекта, поэтому числовые сегменты работают только если базовое значение — объект с таким числовым ключом (в виде строки). Чтобы выбрать элемент из массива, используйте Code node. - Optional chaining (
?.), null coalescing (??), значений по умолчанию — не поддерживаются. Отсутствующий путь разрешается вundefined, и всё. - Вызовов функций, фильтров и выражений — в языке шаблонов нет операторов. Если нужны
toUpperCase(),slice(), арифметика или условная логика — используйте Code node.
Приведение типов
Когда выражение подставляется во вход коннектора, исполнитель приводит разрешённое значение к объявленному типу свойства. Правила лежат в — одна стратегия на тип свойства:
NUMBER— если уже число, проходит без изменений. ИначеNumber(value); бросаетVALIDATION_ERROR, если результатNaN. Так{{trigger.age}}, возвращающий строку"25", становится25.CHECKBOX— булевы значения проходят. Строки"true"/"1"(без учёта регистра) →true;"false"/"0"→false. Всё остальное бросаетVALIDATION_ERROR.SHORT_TEXT— всегдаString(value). Числа, булевы, даже объекты становятся строковым представлением.LONG_TEXT— то же, чтоSHORT_TEXT:String(value).ARRAY— массивы проходят. Строка парсится как JSON и принимается, если парсится в массив; иначе бросается ошибка. Нестроковые и немассивные значения проходят без изменений (коннектор получает то, что есть).OBJECT— объекты проходят (включаяnull, так какtypeof null === "object"). Строки парсятся как JSON; результат должен быть ненулевым объектом, иначе бросается ошибка. Нестроковые и необъектные значения проходят без изменений.DROPDOWN,DYNAMIC_DROPDOWN,OAUTH2,SECRET_TEXT,DATE_TIME— идентичность. Значение передаётся нетронутым; парсинг — ответственность коннектора.
Null-безопасность повсеместно: если разрешённое значение — null или undefined, приведение пропускается и сырое null/undefined передаётся как есть. Отсутствующее поле никогда не бросает ошибку на этапе приведения — обычно оно падает позже, когда коннектор валидирует обязательные входы.
Экранирование
Механизма экранирования для литеральных {{ или }} нет. Регулярное выражение — \{\{([^}]+)\}\}: любая пара двойных скобок с не-} содержимым внутри считается шаблоном. Вывести в тексте литерал {{foo}} нельзя; если это действительно нужно, соберите строку в Code node и верните её оттуда.
На практике это практически никогда не случается — входы workflow это значения, а не исходник шаблонов.
Отсутствующие пути
Это намеренное поведение, о котором стоит знать:
- Неизвестный корневой ключ →
undefined. Если вы пишете{{tyop.field}}, а узла с IDtyopне было, выражение разрешается вundefined. Резолвер не ищет подходящий ключ в остальных данных. Это сознательно — так опечатки и сломанные ссылки всплывают, а не подхватывают случайное значение. - Неизвестный вложенный сегмент →
undefined. Проход по отсутствующему ключу или черезnullдаётundefined. - Inline-шаблоны приводят
undefinedк"". ТакHello {{trigger.unknown}}!отрендерится какHello !. - Whole-value-шаблоны сохраняют
undefined. Сопоставление поля, всё значение которого —{{trigger.unknown}}, пробрасываетundefined, и (по правилам приведения выше) приведение его пропускает. Ошибка обычно всплывает на валидации обязательных полей на границе коннектора.
Глобального фолбэка и автопоиска нет. Если вы адресуете узел, не являющийся предком текущего, получаете undefined.
Частые ошибки
- Голые имена полей не работают.
{{email}}выглядит естественно, но разрешается вundefined, если только нет узла с IDemail. Почти всегда имеется в виду{{trigger.email}}или{{some_action.email}}. Корневой сегмент — это node ID, а не имя поля. - Опечатки молча возвращают
undefined.{{trigger_1.emial}}(переставлены буквы) возвращаетundefined, что в inline-контексте становится"". Если ниже по потоку узел отправляет пустую строку там, где должно быть значение, начните с проверки написания пути. - Числа из некоторых источников приходят строками. Тела вебхуков, URL-параметры и поля форм часто приходят строками. Свойства типа
NUMBERприводят их за вас;SHORT_TEXT— нет (нечего приводить). Но если вы пишете условие против{{trigger.body.count}}, ожидая целочисленного сравнения, помните: сырое значение может быть"25", а не25. Операторы условий это учитывают, но своя логика в Code node должна тоже. - Нет индексации массива.
{{list_rows_1.rows.0.name}}не вытаскивает первую строку — он ищет ключ, буквально называемый"0", наrows. Массивы результатов требуют Loop node или Code node для выбора элементов. - Ссылка на соседнюю ветвь. Узел видит выходы только своих предков в DAG. Ссылка
{{other_branch.result}}на узел в параллельной ветви, которая ещё не запускалась, разрешится вundefined. Если нужны данные из другой ветви, сначала объедините ветви.
Смотрите также
- Передача данных между узлами
- Обзор конструктора workflow
- Code node — для всего, что не выразить языком шаблонов