Переменные

Чтобы использовать переменные, объявите их в отдельном блоке variables. При объявлении переменной укажите параметры:

  • name — имя, может состоять из латинских букв разных регистров, цифр и символов _ и .. Не может начинаться с цифры или с точки.
  • type — тип переменной. См. Типы данных.
  • value — значение по умолчанию.

Например:

{
    "variables": [
        {
            "name": "subscribed",
            "type": "boolean",
            "value": true
        }
    ],
}

Типы данных

Поддерживаемые типы данных:

  • логический: boolean
  • строковый: string
  • целочисленный: integer
  • число с плавающей точкой: number
  • цвет: color
  • ссылка на ресурс: url
  • словарь: dict
  • массив: array
Примеры объявления переменных
{
    "variables": [
        {
            "name": "subscribed",
            "type": "boolean",
            "value": true
        },
        {
            "name": "likes",
            "type": "integer",
            "value": 0
        },
        {
            "name": "black",
            "type": "color",
            "value": "#f000"
        },
        {
            "name": "username",
            "type": "string",
            "value": "unknown"
        }
    ],
    "states": [ ... ]
}

Словари

В качестве переменной можно объявлять словари — произвольные JSON-объекты, внутри которых могут храниться любые другие типы переменных.
Например, их удобно использовать для объявления палитры и получать из нее значения в зависимости от темы приложения:

"variables": [
  {
    "name": "palette",
    "type": "dict",
    "value": {
      "light": {
        "text_color": "#ffffff",
        "text_background": "#0077FF"
      },
      "dark": {
        "text_color": "#000000",
        "text_background": "#0077FF"
      },
      "big": {
        "text_size": 20
      },
      "small": {
        "text_size": 16
      }
    }
  },
  {
    "name": "app_theme",
    "type": "string",
    "value": "light"
  },
  {
    "name": "font_size",
    "type": "string",
    "value": "small"
  }
]

Словарь не может самостоятельно определять типы, поэтому нужно правильно выбирать функции для того, чтобы получить переменную из словаря:

getIntegerFromDict(dict_name, path_to_value)
getNumberFromDict(dict_name, path_to_value)
getStringFromDict(dict_name, path_to_value)
getColorFromDict(dict_name, path_to_value)
getUrlFromDict(dict_name, path_to_value)
getBooleanFromDict(dict_name, path_to_value)
getOptIntegerFromDict(fallback, dict_name, path_to_value)
getOptNumberFromDict(fallback, dict_name, path_to_value)
getOptStringFromDict(fallback, dict_name, path_to_value)
getOptColorFromDict(fallback, dict_name, path_to_value)
getOptUrlFromDict(fallback, dict_name, path_to_value)
getOptBooleanFromDict(fallback, dict_name, path_to_value)

В объявленном словаре из примера значения цветов и размера шрифта можно использовать так:

"background": [
  {
    "type": "solid",
    "color": "@{getColorFromDict(palette, app_theme, 'text_background')}"
  }
],
"font_size": "@{getIntegerFromDict(palette, font_size, 'text_size')}",
"text_color": "@{getColorFromDict(palette, app_theme, 'text_color')}"
Посмотреть интерактивный пример

Массивы

Массивы содержат произвольные JSON-объекты.

"variables": [
  {
    "type": "array",
    "name": "array",
    "value": [
      "string",
       123,
      "@{expression}"
    ]
  }
]

Массив, как и словарь, не может автоматически определять типы переменных, которые хранятся внутри него, поэтому нужно правильно выбирать функции для того, чтобы получить значение из массива:

getIntegerFromArray(array, index)
getNumberFromArray(array, index)
getStringFromArray(array, index)
getColorFromArray(array, index)
getUrlFromArray(array, index)
getBooleanFromArray(array, index)
getArrayFromArray(array, index)
getDictFromArray(array, index)
getOptIntegerFromArray(array, index, fallback)
getOptNumberFromArray(array, index, fallback)
getOptStringFromArray(array, index, fallback)
getOptColorFromArray(array, index, fallback)
getOptUrlFromArray(array, index, fallback)
getOptBooleanFromArray(array, index, fallback)
getOptArrayFromArray(array, index, fallback)
getOptDictFromArray(array, index, fallback)

getArrayLength(array)

Если тип функции выбран неправильно или произошел выход за границы массива, возникнет ошибка. В этом случае можно использовать функцию getOpt* вместо get*, тогда вместо ошибки возвратится fallback значение.

Посмотреть интерактивный пример

Методы

Для работы с массивами и словарями удобно применять методы. В отличие от функций, они вызываются непосредственно из массива или словаря и возвращают требуемое значение.

Доступные методы

Название

Описание

Тип результата

toString

Преобразует значение переменной любого типа в строку.

string

getArray

Позволяет получить массив из словаря (массива) по ключу (индексу).

array

getDict

Позволяет получить словарь из словаря (массива) по ключу (индексу).

dict

getBoolean

Позволяет получить логическое значение из словаря (массива) по ключу (индексу).

boolean

getColor

Позволяет получить значение цвета из словаря (массива) по ключу (индексу).

color

getInteger

Позволяет получить целое число из словаря (массива) по ключу (индексу).

integer

getNumber

Позволяет получить число с плавающей точкой из словаря (массива) по ключу (индексу).

number

getString

Позволяет получить строку из словаря (массива) по ключу (индексу).

string

getUrl

Позволяет получить URL из словаря (массива) по ключу (индексу).

url

isEmpty

Проверяет, является ли массив (словарь) пустым, и возвращает соответствующее логическое значение boolean.

Полные описания полей методов и примеры использования доступны в репозитории DivKit:

Значения полей

В описании метода заполнены следующие поля:

  • function_name — название метода.

  • is_method — флаг, показывающий, является ли функция методом. Для всех методов имеет значение true.

  • doc — описание работы метода.

  • arguments — список аргументов. Каждый аргумент описывается значениями:

    • type — тип;

    • doc — описание;

    • vararang — опциональный флаг, разрешающий передавать в качестве этого аргумента не одно, а несколько значений нужного типа.

  • result_type — тип возвращамого значения.

Посмотреть интерактивный пример

Изменение значений переменных

Для изменения значения переменной доступно действиеset_variable. Например:

div-action://set_variable?name=common_text_size&value=17

Чтобы задать значение переменной, можно использовать вычисляемые выражения и встроенные функции.

Изменить значения переменных также можно через SDK (в Android с помощью DivView#setVariable ).

Примечание

Важно, чтобы тип нового значения совпадал с типом переменной, иначе будет невозможно применить значение.

Примеры:

  • изменить значение переменной с плавающей точкой:

    div-action://set_variable?name=price&value=3.889
    
  • изменить значение логической переменной:

    • значение true: div-action://set_variable?name=is_liked&value=1
    • значение false: div-action://set_variable?name=is_liked&value=0
  • изменить значение переменной типа color на зеленый цвет:

    div-action://set_variable?name=color_variable&value=@{encodeUri('#ff00ff00')}
    

Внешние переменные

Переменные, которые объявляются в верстке, являются переменными уровня карточки и недоступны извне. Для совместного использования переменных между разными верстками нужно использовать внешние переменные.

Для этого объявите DivVariableController на клиенте и передайте в него переменные, к которым нужно обращаться из верстки.

Пример для Android

Объявим DivVariableController при создании DivConfiguration:

val variableController = DivVariableController()
val configuration = DivConfiguration.Builder(imageLoader)
    .divVariableController(variableController)
    .build()

Теперь в контроллер можно передать переменную. Для примера передадим строковую переменную app_theme:

val theme = Variable.StringVariable("app_theme", "light")
variableController.putOrUpdate(theme)

Теперь во всех Div2View, созданных с помощью данной DivConfiguration, будет доступна переменная app_theme. Чтобы изменить значение переменной, в коде можно использовать метод DivVariable#set. Если эта переменная уже объявленна в контроллере — ее значение также обновится.

Пример для iOS

Объявим DivVariableController в DivKitComponents:

let variablesStorage = DivVariablesStorage()
let divkitComponents = DivKitComponents(variablesStorage: variablesStorage)

Теперь в контроллер можно передать переменную. Для примера передадим словарь с палитрой:

let themeVariable: DivVariables = [
  DivVariableName(rawValue: "palette"): .dict([
    "text_color": "#ffffff",
    "text_background": "#0077FF"
  ])
]
variablesStorage.put(themeVariable)

Теперь во всех Div2View, созданных с помощью данного DivKitComponent, будет доступна переменная pallete.

Пример для Web

Создадим GlobalVariablesController:

import {createVariable, createGlobalVariablesController} from '@divkitframework/divkit';

const controller = createGlobalVariablesController();

Теперь в контроллер можно передать переменную, например словарь с палитрой:

const palette = createVariable('palette', 'dict', {
  "text_color": "#ffffff",
  "text_background": "#0077FF"
});
controller.setVariable(palette);

Теперь во всех экземплярах класса, созданных с использованием данного controller, будет доступна переменная pallete.

Внимание

Переменные уровня карточки имеют больший приоритет, чем внешние. Если объявить в верстке переменную уровня карточки с тем же названием, что и у внешней, то внешняя переменная станет недоступна. Также изменение внешней переменной из верстки поменяет ее и в DivVariableController, то есть и во всех остальных верстках, где используется эта переменная.

Переменные уровня элемента

Переменные уровня элемента объявляются в верстке внутри элемента, который они характеризуют.

Примечание

Раньше можно было объявлять только переменные уровня карточки (для объекта card). Сейчас можно объявлять переменные для любого элемента.

Посмотреть интерактивный пример

Выполнение действий при изменении значений переменных

После изменения значения переменной, кроме обновления всех свойств, в которых используется переменная, можно выполнить любое количество действий. Для этого добавьте описание триггера в блоке variable_triggers:

  • Параметр condition — условие выполнения действия. Может содержать логическое выражение с использованием переменных или события, по которым будет запущен триггер.

  • Параметр mode — определяет, в каком случае срабатывает действие:

    • on_condition — действие срабатывает, если при изменении значения переменной стало выполняться условие (до этого условие не выполнялось);
    • on_variable — действие срабатывает каждый раз, если при изменении значения переменной условие выполняется.

    Например, переменные меняются несколько раз и condition последовательно принимает значения true → true → false → true. При использовании значения on_condition действие сработает 2 раза, при использовании значения on_variable — 3 раза.

  • Параметр actions — описание действий, которые требуется выполнить при выполнении условия.

Ограничения:

  • Условия без использования переменных (к примеру "condition": "@{1 == 1}") или с функциями, не зависящими от переменных, не будут работать, так как без переменных не ясно, когда именно следует запускать проверку условия.
  • Триггер не будет срабатывать, если в условии сравниваемые между собой сущности будут иметь разные типы (к примеру, переменная логического типа сравнивается с переменной типа integer).

Например:

{
    "states": { ... },
    "variables": { ... },
    "variable_triggers": [
        {
            "condition": "@{liked}",
            "actions": [
                {
                    "url": "div-action://set_variable?name=total_likes&value=@{sum(total_likes, 1)}"
                }
            ]
        },
        {
            "condition": "@{subscribed && !liked}",
            "mode": "on_condition",
            "actions": [
                {
                    "url": "div-action://set_state?state_id=0/subscriptions/expanded"
                },
                {
                    "log_id": "common_posts_shown",
                    "url": "div-action://set_state?state_id=0/common_posts/collapsed"
                }
            ]
        },
        {
            "condition": "@{total_likes > 100 || user_name == 'John'}",
            "mode": "on_variable",
            "actions": [ ... ]
        }
  ]
}

В примере выше первый триггер будет запускать действие, которое увеличивает значение переменной total_likes каждый раз, когда значение переменной liked сменится с false на true . По такой же логике будет работать и второй триггер.

Третий триггер, благодаря параметру "mode": "on_variable", будет запускаться каждый раз при изменении значений переменных и выполнении условия в condition .

Узнать больше

Следите за новостями DivKit в Telegram-канале: http://t.me/divkit_news.

Также вы можете обсуждать интересующие вас темы в сообществе пользователей DivKit в Telegram: https://t.me/divkit_community_ru.

Репозиторий DivKit

Триггеры уровня элемента

Триггеры уровня элемента срабатывают при изменении значения переменной уровня элемента. Их формат такой же, как у внешних триггеров.

Триггер уровня элемента:

  • имеет доступ к переменным уровня элемента у родительского объекта;

  • срабатывает даже для невидимых элементов (с параметром "visibility" = "gone"/"invisible");

  • не срабатывает в состояних и табах, которые сейчас не активны.

При переходе в новое состояние или на другой таб:

  • если состояние (таб) активируется впервые, то триггер срабатывает при выполнении условия в condition;

  • если раньше уже произошла инициализация состояния (таба) и до выхода из него условие не выполнялось, то триггер сработает, когда условие начнет выполняться.

Посмотреть интерактивный пример
Предыдущая