Расширенные повторения
Расширенные шаблоны для групп повторений: динамическое количество, вложенные повторения, обобщение данных повторений и ссылки на значения между повторениями.
На этой странице рассматриваются расширенные шаблоны работы с группами повторений в rtSurvey. Основы настройки группы повторений см. в разделе Группировка и повторения.
Динамическое количество повторений
По умолчанию перечислитель решает, сколько раз повторять. Можно зафиксировать количество повторений с помощью repeat_count:
| type | name | label | repeat_count |
|---|---|---|---|
| begin_repeat | household_members | Член домохозяйства | ${num_members} |
| text | member_name | Имя члена | |
| integer | member_age | Возраст | |
| end_repeat |
Повторение выполняется ровно ${num_members} раз, где num_members был собран ранее в форме. Перечислитель не может добавлять или удалять экземпляры.
Индексированный доступ: indexed-repeat()
Получите доступ к значению поля конкретного экземпляра повторения извне группы с помощью indexed-repeat(repeatedField, repeatGroup, index):
| type | name | label | calculation |
|---|---|---|---|
| calculate | first_name | indexed-repeat(${member_name}, ${household_members}, 1) | |
| calculate | second_name | indexed-repeat(${member_name}, ${household_members}, 2) |
Это полезно для создания сводных полей или ссылки на данные «первичного» члена после повторения.
Позиция текущего экземпляра: index()
Внутри группы повторений index() возвращает 1-базированную позицию текущего экземпляра. Используйте для нумерации повторений или создания уникальных идентификаторов:
| type | name | label |
|---|---|---|
| begin_repeat | plots | Участок |
| note | plot_label | Участок номер ${index()} |
| text | plot_id | ID участка |
| end_repeat |
Ссылки на поля в том же экземпляре
Внутри повторения используйте ${fieldname} для ссылки на другое поле в том же экземпляре повторения. indexed-repeat() внутри одного цикла не нужен:
| type | name | label | relevant |
|---|---|---|---|
| begin_repeat | members | Член | |
| text | member_name | Имя | |
| integer | member_age | Возраст | |
| text | school_name | Название школы | ${member_age} < 18 |
| end_repeat |
Ссылки на родительские поля из повторения
Поля вне (выше) группы повторений можно использовать в ссылках обычным образом через ${fieldname}:
| type | name | label |
|---|---|---|
| text | village | Название деревни |
| begin_repeat | plots | Сельскохозяйственный участок |
| note | plot_context | Участки в ${village} |
| end_repeat |
Обобщение данных повторений
Используйте агрегирующие функции повторений вне группы для обобщения:
| Функция | Пример | Описание |
|---|---|---|
count(group) | count(${household_members}) | Количество экземпляров |
sum(field) | sum(${loan_amount}) | Сумма числового поля |
min(field) | min(${member_age}) | Минимальное значение |
max(field) | max(${member_age}) | Максимальное значение |
join(sep, field) | join(', ', ${member_name}) | Список через запятую |
count-if(group, expr) | count-if(${members}, ${member_age} < 18) | Условный подсчёт |
sum-if(field, expr) | sum-if(${loan_amount}, ${loan_amount} > 500) | Условная сумма |
join-if(sep, field, expr) | join-if(', ', ${name}, ${age} >= 18) | Условное объединение |
Пример: Сводка домохозяйства
| type | name | label | calculation |
|---|---|---|---|
| integer | num_members | Сколько членов? | |
| begin_repeat | members | Член | ${num_members} |
| text | member_name | Имя | |
| integer | member_age | Возраст | |
| end_repeat | |||
| calculate | total_members | count(${members}) | |
| calculate | children_count | count-if(${members}, ${member_age} < 18) | |
| calculate | adult_names | join-if(', ', ${member_name}, ${member_age} >= 18) | |
| note | summary | ${total_members} членов; ${children_count} до 18 лет. Взрослые: ${adult_names} |
Вложенные повторения
Группа повторений может содержать другую группу повторений. Используйте с осторожностью — вложенные повторения добавляют сложность.
| type | name | label |
|---|---|---|
| begin_repeat | households | Домохозяйство |
| text | hh_id | ID домохозяйства |
| begin_repeat | hh_members | Член |
| text | member_name | Имя члена |
| end_repeat | ||
| end_repeat |
Для ссылки на поле внешнего повторения из внутреннего используйте ${fieldname} — оно разрешается до ближайшего подходящего предка.
Внутри повторения hh_members ${hh_id} возвращает ID текущего домохозяйства, а не всех домохозяйств.
Ранжирование внутри групп повторений: rank-index()
Когда поле rank находится внутри повторения, используйте rank-index(instanceNumber, repeatedField) извне для получения порядкового ранга конкретного экземпляра:
| type | name | label | calculation |
|---|---|---|---|
| calculate | top_scorer | rank-index(1, ${score}) |
rank-index(1, ${score}) возвращает индекс экземпляра с наивысшим значением.
Лучшие практики
- Всегда используйте
repeat_count, когда количество повторений известно заранее — это предотвращает случайное добавление или удаление экземпляров перечислителем. - Делайте группы повторений сфокусированными — повторение с 20+ вопросами на экземпляр трудно навигировать.
- Называйте группы повторений ясно (например,
household_members, а неrepeat1) — имя появляется в вызовах функций и экспортированных данных. - Тестируйте с максимально ожидаемым количеством экземпляров для проверки производительности.
- Используйте внешний вид
field-listдля группы повторений, чтобы показывать все поля на одном экране на экземпляр (мобильные).
Ограничения
indexed-repeat()требует допустимого индекса (от 1 до количества экземпляров) — выход за пределы возвращает пустое значение.- Вложенные повторения глубже 2 уровней не рекомендуются и могут вызывать проблемы отображения в некоторых клиентах.
- Агрегирующие функции (
sum,countи т.д.) работают со всей группой повторений — нельзя агрегировать подмножество экземпляров без вариантов*-if.