Контейнеры с динамическим набором данных

В DivKit есть возможность создавать контейнеры, галереи и пейджеры с динамическим набором данных. В этом случае элементы контейнера не зашиты в верстку, а задаются при помощи вычисляемого выражения. Для этого используется свойство item_builder.

Простой пример

{
  "type": "container",
  "item_builder": {
    "data": [
      {
        "text": "Item 1"
      },
      {
        "text": "Item 2"
      }
    ],
    "data_element_name": "item",
    "prototypes": [
      {
        "div": {
          "type": "text",
          "text": "@{item.getString('text')}"
        }
      }
    ]
  }
}

В этом примере:

  • data — массив данных, который будет использоваться для формирования элементов контейнера.

  • data_element_name — название переменной, содержащей данные для текущего элемента. Эта переменная доступна только внутри прототипа.

    Если параметр data_element_name не указан, переменная для доступа к данным внутри прототипа по умолчанию называется it.

  • prototypes — набор прототипов, по которым формируются элементы контейнера. Прототип — это элемент верстки, который клонируется для каждого элемента данных (из массива data).

В верстке из примера мы получим контейнер с двумя элементами:

  • Внутри первого элемента переменная item (типа dict_variable) будет содержать следующее значение: { "text": "Item 1" }.

  • Внутри второго элемента переменная item будет содержать значение: { "text": "Item 2" }.

В итоге получится контейнер с двумя текстовыми элементами:

Item 1
Item 2

Динамический набор данных

Усложним пример: не будем зашивать данные в описание самого контейнера, а используем переменную.

{
  "type": "container",
  "item_builder": {
    "data": "@{items}",
    "data_element_name": "item",
    "prototypes": [
      {
        "div": {
          "type": "text",
          "text": "@{item.getString('text')}"
        }
      }
    ]
  }
}

Например, переменная items объявлена в самой карточке и содержит те же значения, что и свойство data в первом примере:

{
  "name": "items",
  "type": "array",
  "value": [
    {
      "text": "Item 1"
    },
    {
      "text": "Item 2"
    }
  ]
}

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

Неоднородные данные

В контейнере могут содержаться элементы с разной версткой. Например, изображения и текстовые блоки. Это также можно реализовать при помощи прототипов:

{
  "type": "container",
  "item_builder": {
    "data": [
      {
        "type": "text",
        "text": "Item 1"
      },
      {
        "type": "text",
        "text": "Item 2"
      },
      {
        "type": "image",
        "url": "https://image.url"
      }
    ],
    "data_element_name": "item",
    "prototypes": [
      {
        "selector": "@{item.getString('type') == 'text'}",
        "div": {
          "type": "text",
          "text": "@{item.getString('text')}"
        }
      },
      {
        "selector": "@{item.getString('type') == 'image'}",
        "div": {
          "type": "image",
          "image_url": "@{item.getUrl('url')}"
        }
      }
    ]
  }
}

В свойстве prototypes заданы два прототипа. Для выбора соответствующего элементу данных прототипа используется свойство selector. В selector можно прописать выражение, которое возвращает булево значение. Оно означает, подходит ли прототип для текущего элемента данных. Если условию удовлетворяют несколько прототипов, то используется первый.

Использование переменных в прототипах

Внутри каждого прототипа доступны:

  1. Текущий элемент данных через переменную, указанную в data_element_name (или it, если не указано)
  2. Индекс текущего элемента через переменную index

Эти переменные автоматически доступны в области видимости прототипа и могут использоваться в выражениях. Например, можно использовать @{item.getString('name')} для доступа к полю из текущего элемента данных или @{index} для получения позиции текущего элемента в массиве.

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

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

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

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