Понимание запросов Om и состава пользовательского интерфейса
Я пытался обернуть голову вокруг вопросов. Допустим, я хочу Root
компонент с несколькими табличными представлениями на нем.
Официальный учебник предлагает - один из подходов - иметь компонент табличного представления без запроса. И затем вы можете передавать любые необходимые данные через реквизит, и это прекрасно работает.
Но это очень простой случай. В нетривиальном приложении, вероятно, вы хотели бы иметь TableView
с запросом, поскольку вниз по дереву пользовательского интерфейса у вас может быть некоторая сложная структура компонентов пользовательского интерфейса - верхний колонтитул таблицы, нижний колонтитул, строки, ячейки и т. д. Теперь в этом руководстве предлагается подход с запросом:
И все же это все еще несколько упрощенный пример. Так скажем, если у меня есть:
(defmethod read :numbers/odd [_ _ _]
{:value (filter odd? (range 50))})
(defmethod read :numbers/even [_ _ _]
{:value (filter even? (range 50))})
в реальном приложении, конечно, данные будут поступать из серверной части, а Ом будет вставлять их в атом состояния (как обычно)
теперь мне нужно иметь TableView
компонент с запросом, который может визуализировать любой из них (или любую последовательность в этом случае). Итак, вы видите, я должен как-то рассказать TableView
компонент для использования данных, которые находятся где-то еще в атоме состояния. И запрос для TableView
должно быть "динамическим", поэтому я могу использовать несколько TableViews
рендеринг разных данных.
Допустим, у нас будет что-то вроде этого для Root:
(defui Root
(query [_] [{:table/odd ,,,} {:table/even ,,,}])
(render
[this]
(let [{:keys [table/odd table/even]}]
(html [:div
[:div.odds (ui-table-view odd)]
[:div.evens (ui-table-view even)]]))))
для пивоварения я опустил интерфейсы Om.Next
Теперь у меня есть несколько вопросов:
- Как следует запросить для
Root
выглядит как? - Должен ли я иметь параметризованный запрос в
TableView
(где я мог бы указать ключ для данных в атоме состояния)? Или как еще я могу сказать одноTableView
использовать:numbers/odd
а другой использовать:numbers/even
? - Если я использую параметризованный запрос в
TableView
тогда как мне передать параметры отRoot
вTableView
? - Может быть, я должен передать данные или ссылку на данные TableView через вычисленные реквизиты?
- Как бы я использовал тогда
om/get-query
(если подзапрос параметризован)? - Как бы выглядели методы чтения? Нужно ли "перемещать вещи" в атоме в
read
? Не похоже на хорошую идею
Может кто-нибудь, пожалуйста, покажите мне какой-нибудь пример. Большое спасибо!.
1 ответ
Вот что я придумала:
Для каждой таблицы сохраните связанный с ней ключ данных, а затем на этапе чтения получите эти данные и сопоставьте их с картой, представляющей таблицу:
Итак, если у нас есть пара таблиц (с нечетными и четными числами):
{:app/tables
[{:id 0
:title "Odd numbers"
:data-key :data/odds}
{:id 1
:title "Even numbers"
:data-key :data/evens}]}
Этот метод чтения выглядит так:
(defmethod parsing/read :app/tables
[{:keys [state parser] :as env} k _]
(let [ts (get @state k)
merge-table-data' (fn [{:keys [data-key] :as t}]
(assoc t :table/data
(->> data-key
vector
(parser env)
vals
flatten)))]
{:value (map merge-table-data' ts)}))
У этого подхода есть один большой недостаток - он будет пытаться проанализировать ВСЕ данные для всех таблиц, поэтому мне нужно найти способ его улучшить - я хочу иметь возможность выборочно указывать таблицы для сбора данных.
Фрагмент для всего решения здесь:
upd: я сделал улучшенную версию (добавил файл в суть). В этом примере теперь вы можете указать ключи данных, чтобы он загружал только указанные куски
upd2: Видимо, этот подход как-то ломает мутации. Идея, тем не менее, правильна - нужно использовать механику нормализации Om.Next. Я постараюсь обновить суть позже.