Flexibile form (fform) — построитель форм с минимальной избыточностью кода, при этом максимально гибкий и расширяемый. Используемый стэк технологий: React (v16), Redux (опционально), JSONSchema, TypeScript. Основная идея — максиально возможное повторное использование схем, компонентов и функций.
Особенности
- 98kb минифицированный, 28kb сжатый
- Конструктор форм для быстрого старта
- Комбинирование и переиспользование форм или их частей при использовнии свойств
oneOf
,allOf
,$ref
- Валидация sync/async/JSON/submit
- Нативная поддержка redux, но возможно использовать любое другое хранилище (в т.ч. внутреннее)
- Полная поддержка массивов (добавление/удаление/перемещение)
- Встроенный просмотрщик
- Полностью настраиваемые и добавляемые элементы формы
- Поддержка SSR
- Без зависимостей (React как внешняя)
Так как по спецификации JSONSchema определяется данными только в формате JSON, в fform форма задаётся 2-мя объектами:
- схема JSONSchema (draft v4, с дополнительными свойствами), содержащая только JSON-данные и описывающая поля формы и расположение объектов вроде кнопок, ссылок, табов и т.п.
- объект elements, содержащий компоненты React(v16), функции, часто используемые части компонентов и, в принципе, любой другой js или JSON код, на который есть возможность ссылаться как из любой части объекта elements так и из расширенных полей объекта JSONSchema. В своей сути, elements — это хранилище кирпичиков кода из которых потом собирается вся форма, причем степень элементарности этих кипричиков определяется самим разработчиком.
Гибкость, расширяемость и повторное применение готовых схем, компонентов и функций реализуется следующим образом:
- Расщирение схем при использовании свойств $ref и allOf так, как это описано в спецификации JSONSchema. Ссылка на пример.
- Расширение объекта elements при использовании схожего принципа, но с другим синтаксисом (чтобы визуально различать где расширяется схема, а где elements). Документация. Ссылка на пример.
- Обработчики данных и событий используют конвеер(pipes) из js-функций примерно так, как это сделано в linux. Выход одной функции подается на вход следующей, что (при правильном разделении ответственности функций) позволяет переиспользовать уже существующими функции, а новые добавлять только если требуется еще не реализованная функциональность. Документация. Ссылка на пример.
Ссылки
Автор: wtnm7