whamtet / simpleui

JS Free Single Page Applications
https://whamtet.github.io/simpleui/
Eclipse Public License 2.0
246 stars 15 forks source link

rt/mapped-index and forms.. how should it work? #13

Closed Ramblurr closed 1 year ago

Ramblurr commented 1 year ago

(note: This is probably not a bug as much as it is a user support question. I'm happy to take these questions to a different medium if you want.)

I think I must be doing something wrong because I'm not seeing the benefit of rt/map-indexed.

See in the code snippet below. When GET'd from the top-level there are no issues.

But when the form is submitted the function/component params (idx and person-id) are nil. So I am forced to calculate these from the params map. Also notice the lack of (value "..") usage.. I've not figured out when using that actually helps.

Am I doing something wrong?


(defcomponent ^:endpoint a-form [req idx person-id]
   ;; why is (value "person-id") always nil both on GET and POST
  (tap> {:person-id-value (value "person-id")})

  (ctmx/with-req req
    (let [params    (-> req :form-params form/json-params-pruned)
          idx       (or idx (:idx params))
          person-id (or person-id (:person-id params))
          person    (cond post? (update-person! (:person-id params) (:name params) (:email params))
                          :else (person-by-id person-id))]
      ;; (tap> {:idx idx :person-id person-id :person person :this id :params params :raw-params (:params req)})
      [:li {:id id :style (str (when (= 0 (mod idx 2)) "background-color: #ccc;") " list-style:none;")}
       [:form {:hx-post "a-form"}
        [:input {:type "hidden" :name (path "idx") :value idx}]
        [:input {:type "hidden" :name (path "person-id") :value person-id}]
        [:input {:type "text" :name (path "name") :value (:person/name person)}]
        [:input {:type "email" :name (path "email") :value (:person/email person)}]
        [:button {:type :submit :hx-target (hash ".")} "Save"]]])))

(defcomponent ^:endpoint mapped-forms [req]
  [:div
   [:h2 "People"]
   [:ul
    (rt/map-indexed a-form req (map :person/person-id (vals @people)))]])

The issue seems to arise when using the mapped component as an endpoint itself.

In this trivial example one could have a single <form> pulled up to the top level and submit all person records at once.

But in my real use case, the number of records is large and I only want to submit on a person-by-person basis.

whamtet commented 1 year ago

Nice use case, I decided to get rid of ctmx/with-req because its better to use middleware instead. For an example see here. The difference is middleware applies a function to the request map before it binds to the component arguments which is more consistent.

As for rt/map-indexed it may be easier to discuss in a call, please email me matthew@molloy.link

Ramblurr commented 1 year ago

Just a quick other example of this to discuss on our call. when you have nested components and the leaves are endpoints which are POSTed too, the id changes between the initial rendering and the subsequent POST.

For example. Given four components a, b, c, and d. a maps over b, and b maps over c. And c simply calls d

component-d does something like this

(ctmx/defcomponent ^:endpoint component-d [req]
  ...
  [:form {:id id :hx-target (hash ".")} ...
    [:button {:hx-post "component-d"}.. ] 

During the initial render:

But during a POST to component-a_component-b_0_component-c_component-d_0, inside the component function

I suspect this has something to do with an incorrect hx-post val.

whamtet commented 1 year ago

Are you still getting this with 1.4.7? I cleaned up the way I handle IDs, basically the true id order should be component-a_0_component-b_0_component-c_component_d. We have to rearrange that to correctly convert to JSON, but its more sensible to do that when you actually convert rather than re-arranging the indexes during render. If you pull 1.4.7 you should see this new correct id.

Matt

On Nov 9, 2022, at 17:40, Casey Link @.***> wrote:

Just a quick other example of this to discuss on our call. when you have nested components and the leaves are endpoints which are POSTed too, the id changes between the initial rendering and the subsequent POST.

For example. Given four components a, b, c, and d. a maps over b, and b maps over c. And c simply calls d

component-d does something like this

(ctmx/defcomponent ^:endpoint component-d [req] ... [:form {:id id :hx-target (hash ".")} ...] During the initial render:

for a[0] and b[0] id will = component-a_component-b_0_component-c_component-d_0 for a[0] and b[1] id will = component-a_component-b_0_component-c_component-d_1 etc.. looks good. But during a POST to component-a_component-b_0_component-c_component-d_0, inside the component function

id is now component-a_component-b_0_component-c_component-d_component-d the second index is lost and somehow replaced with a dupe of component-d this can result in multiple non-unique ids every time the form is submitted for a different a[idx] — Reply to this email directly, view it on GitHub https://github.com/whamtet/ctmx/issues/13#issuecomment-1308402663, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOSIP6BPOIHJMW25WDS6ODWHNPRNANCNFSM6AAAAAARZHGE6A. You are receiving this because you modified the open/close state.

whamtet commented 1 year ago

here’s a zoom link!

https://us05web.zoom.us/j/86436091766?pwd=V2liR2VTVXIrRnhRNWlhcVQvUWpKZz09

On Nov 10, 2022, at 6:30, Matthew Molloy @.***> wrote:

Are you still getting this with 1.4.7? I cleaned up the way I handle IDs, basically the true id order should be component-a_0_component-b_0_component-c_component_d. We have to rearrange that to correctly convert to JSON, but its more sensible to do that when you actually convert rather than re-arranging the indexes during render. If you pull 1.4.7 you should see this new correct id.

Matt

On Nov 9, 2022, at 17:40, Casey Link @. @.>> wrote:

Just a quick other example of this to discuss on our call. when you have nested components and the leaves are endpoints which are POSTed too, the id changes between the initial rendering and the subsequent POST.

For example. Given four components a, b, c, and d. a maps over b, and b maps over c. And c simply calls d

component-d does something like this

(ctmx/defcomponent ^:endpoint component-d [req] ... [:form {:id id :hx-target (hash ".")} ...] During the initial render:

for a[0] and b[0] id will = component-a_component-b_0_component-c_component-d_0 for a[0] and b[1] id will = component-a_component-b_0_component-c_component-d_1 etc.. looks good. But during a POST to component-a_component-b_0_component-c_component-d_0, inside the component function

id is now component-a_component-b_0_component-c_component-d_component-d the second index is lost and somehow replaced with a dupe of component-d this can result in multiple non-unique ids every time the form is submitted for a different a[idx] — Reply to this email directly, view it on GitHub https://github.com/whamtet/ctmx/issues/13#issuecomment-1308402663, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOSIP6BPOIHJMW25WDS6ODWHNPRNANCNFSM6AAAAAARZHGE6A. You are receiving this because you modified the open/close state.