ClojureScript, Om и Om-Bootstrap: нажмите кнопку, сделайте ввод редактируемым

Я создаю страницу, которая отображает, а затем редактирует информацию о арендаторе с помощью om-boostrap. (Я знаком с Clojure, но новичок в CLJS/Om/React/современной веб-разработке в целом.) Пользовательский интерфейс и функциональные возможности между отображением и редактированием информации о арендаторе аналогичны — оба могут использовать поля ввода; редактирование просто требует, чтобы поля были «текстовыми», а не «статическими», и нужны кнопки «Отправить» и «Отмена».

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как React/Om может изменить такой компонент. Представление определяется следующим образом:

(defcomponent view [{:keys [id] :as app} owner]
  (render
   [_]
   (let [tenant (get @tenants id)]
     (dom/div
      (om/build header/header-view app)
      (dom/div {:class "h3"} "View Tenant\t"
               (utils/button {:on-click (fn []
                                          (om/update-state! owner
                                                            #(assoc app :edit? true))
                                          (om/refresh! owner))}
                             "Edit"))
      (om/build tenant-info {:edit? (:edit? app)
                             :tenant {:id id
                                      :name "Funny name"
                                      :unit-addr "Funny addr"
                                      :rent "Lots of rent"}})))))

Я не буду вставлять сюда всю функцию tenant-view, но она создает входные данные Bootstrap для каждого поля данных арендатора, используя om-bootstrap:

. . .
(let [input-type (if edit? "text" "static")]
    (i/input {:ref "name-display"
              :type input-type
              :label "Tenant Name"
              :label-classname "col-xs-2"
              :wrapper-classname "col-xs-4"
              :value (str name)})
    . . .)

Я пробовал несколько подходов. Я опубликовал свой последний, используя функцию :on-click кнопки для изменения состояния приложения, установив для свойства edit? значение true и запросив повторный рендеринг, чтобы сделать ввод редактируемым.

Это не работает, и я не нахожу указаний в документации React или Om.

  1. Как правильно отображать один и тот же компонент по-разному? (В моем случае поля ввода функции view.)
  2. Какая документация React или Om актуальна?

ОБНОВЛЕНИЕ: я могу сделать входы доступными для редактирования, когда я жестко запрограммирую флаг edit? на true, поэтому проблема не в том, чтобы сделать входы редактируемыми: проблема заключается в переключении с static на text (и, предположительно, наоборот).


person MonkeyWithDarts    schedule 12.12.2015    source источник
comment
Разве вы не можете сделать очень много с точки зрения вариации представления с помощью css? Я просто смотрю на defui TodoItem внизу страницы здесь, где DN имеет класс как завершенный и/или редактируемый, и это происходит прямо из состояния.   -  person Chris Murphy    schedule 13.12.2015
comment
Я предполагаю, что кнопки «отправить» и «отменить» переключают :edit? вернуть значение false, чтобы указать, что запись не редактируется (и не должна быть редактируемыми полями). Еще одна вещь, которую вы, вероятно, захотите, — это установить атрибут «отключено» в полях ввода, когда они не находятся в режиме редактирования — это гарантирует, что люди не смогут попытаться изменить значения полей, прежде чем они выберут редактирование. Очевидно, что когда они нажмут на редактирование, вам нужно будет удалить отключенный атрибут.   -  person Tim X    schedule 14.12.2015
comment
Крис, я внимательно рассмотрю этот пример, чтобы увидеть, демонстрирует ли он то, что я ищу. Тим X, да, это то, что я хотел бы, но, как я уже сказал, проблема, с которой я сталкиваюсь, заключается в том, что поля ввода не устанавливаются в текст (что позволяет редактировать). Статический тип ввода заставляет ввод отображаться как обычный текст, предотвращая редактирование.   -  person MonkeyWithDarts    schedule 15.12.2015


Ответы (2)


Да, проблема связана с пониманием разницы между состоянием приложения и состоянием компонента. В этом случае мы хотим повлиять на состояние приложения, я не очень хорошо понимаю ваш сценарий, но я думаю, что для этого было бы лучше использовать локальное состояние компонента. Вы можете использовать init-state или :state. и вы можете использовать om/update-state! по своему усмотрению. Однако, просто добавив к предыдущему ответу, было бы проще просто использовать om/update!, чтобы повлиять на состояние приложения в вашем сценарии.

(utils/button {:on-click #(om/update! app [:edit?] true)}
                         "Edit")

— это еще один вариант, когда вы можете сделать так, чтобы вектор ключевых слов углублялся в карту так глубоко, как вам нравится.

Это более кратко, но может вызвать предупреждение консоли JS, потому что мы игнорируем event из on-click.

person urbanslug    schedule 24.08.2016

Я думаю, проблема в том, что вы используете om/update-state!, который предназначен для перехода к локальному состоянию компонента, вместо om/transact!, который используется для обновления реквизитов, переданных вашему компоненту. Поэтому попробуйте изменить компонент кнопки на это:

(utils/button {:on-click (fn []
                             (om/transact! owner #(assoc app :edit true)))}
                             "Edit")
person Leeondamiky    schedule 20.12.2015