This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-11-01
Channels
- # aws (2)
- # aws-lambda (18)
- # beginners (68)
- # boot (6)
- # cider (2)
- # clara (2)
- # clojars (27)
- # clojure (68)
- # clojure-austin (5)
- # clojure-berlin (6)
- # clojure-dev (28)
- # clojure-greece (7)
- # clojure-italy (46)
- # clojure-japan (3)
- # clojure-nl (1)
- # clojure-russia (8)
- # clojure-sg (1)
- # clojure-spec (17)
- # clojure-uk (86)
- # clojurescript (82)
- # community-development (2)
- # cursive (18)
- # datomic (11)
- # duct (5)
- # fulcro (254)
- # garden (2)
- # graphql (6)
- # hoplon (19)
- # instaparse (4)
- # kekkonen (2)
- # leiningen (4)
- # luminus (3)
- # lumo (9)
- # off-topic (28)
- # om (7)
- # onyx (38)
- # other-languages (27)
- # portkey (7)
- # protorepl (1)
- # re-frame (56)
- # reagent (64)
- # ring (14)
- # ring-swagger (7)
- # shadow-cljs (255)
- # sql (2)
- # vim (11)
- # yada (10)
Hi, how should I do form submit programmatically in reagent? I have the following code but do not know how to submit this form
(defn logger-iframe [target data]
(r/create-class
{:display-name "logger-iframe"
:component-did-mount (fn []
;; do submit
)
:reagent-render
(fn [target data]
[:iframe
{:style {:position "absolute"
:left "-10000px"
:top "-10000px"}}
[:form#f {:action logger-ext-url
:method "POST"}
[:input {:type "hidden"
:name "target"
:value (encode-uri target)}]
[:input {:type "hidden"
:name "userid"
:value ""}]
[:input {:type "hidden"
:name "Uid"
:value (get-logger-uid)}]
[:input {:type "hidden"
:name "ref"
:value (get-ref)}]
[:input {:type "hidden"
:name "data"
:value (->> data
json-stringify
encode-uri)}]]])}))
@cmal Why do you need the invisible form? I think you could just make an AJAX POST request.
Hmm, I thought you could just add or check some headers, and switching to an invisible form shouldn't be any different from a request from JS. But I may be wrong.
In any case, you can add :ref
attribute to the form, store the passed node in an atom, and call submit
on that node in :component-did-mount
handler. Although I'm not sure whether :iframe
will interfere or not.
@p-himik Does iframe
makes send POST request to another host domain possible? Our frontend code already write this to request for another host. And it works. Direct request will be blocked by browser.
I have no idea what to answer on your first question, I have a very limited experience with CORS. Regarding your second question, take a look at this example: https://gist.github.com/pesterhazy/4d9df2edc303e5706d547aeabe0e17e1
Can ref
be used in a :on-click
method? It seems the !ref
does not have any content util render
completes. Or will it make the :reagent-render
function to run a second time?
ref
can also be called multiple times - make sure to consult React documentation on the matter.
ref
should be called before component-did-mount
.
Do you mean that if I use !ref
in a :on-click
that will not cause :reagent-render
to run again?
Hi, @p-himik Why does this example do the @!ref
in the :component-did-update
method? Does that have a special meaning? Does that mean only when the :reagent-render
function returned can the !ref
get a correct value? If so, I doubt that I use the @!ref
in a :on-click
method will fail because the :reagent-render
have not returned, or because the :reagent-render
will run twice due to deref the !ref
.
@cmal I don't understand what :on-click
method you're talking about - there's none in your example.
You've specified in that example that you want to submit the form in :component-did-mount
. :ref
will work there.
Sorry I am thinking of another :input example, the :on-click
is in a component under :reagent-render
.
So what's the problem? How exactly this :on-click
will be called before the component is rendered?
(defn doumi-pay-helper []
(let [hide-pay-tip (fn [e] (rf/dispatch [:doumi-use-vip-set-show-help false]))
show-tip (rf/subscribe [:doumi-use-vip-rmb-show-help])]
(r/create-class
{:display-name "doumi-pay-helper"
:component-did-mount
(fn [el]
(-> js/document
.-body
(.addEventListener "click" hide-pay-tip false))
(-> js/document
.-body
(.addEventListener "touchend" hide-pay-tip false)))
:component-will-unmount
(fn []
(-> js/document
.-body
(.removeEventListener "click" hide-pay-tip false))
(-> js/document
.-body
(.removeEventListener "touchend" hide-pay-tip false)))
:reagent-render
(fn []
[:span
{:style {:position "relative"
:margin-left (base 8)}
:color "#000"
:on-click (fn [e]
(let [element (.getElementById js/document "icon-question")]
(rf/dispatch [:doumi-use-vip-set-show-help (not @show-tip)])
(rf/dispatch [:doumi-style-set-pay-helper-qm-offsetleft
(-> element get-element-left)])
(rf/dispatch [:doumi-style-set-pay-helper-qm-offsetwidth
(-> element .-offsetWidth)])
(.stopPropagation e)))}
[:i#icon-question.icon.icon-question]
(when @show-tip [pay-tip-triangle])
(when @show-tip [pay-tip])])})))
If used according to the React documentation (remember that I said that :ref
can be called many times), it won't fail where getElementById
works.
@cmal By the way, your code looks like it does something similar to what's already implemented in re-com
library from the authors of re-frame
. You may want to check it out.
https://github.com/Day8/re-com/blob/3cc095d2ca6768e15b45040c3b9645945f5c68b4/src/re_com/popover.cljs
(defn doumi-pay-helper []
(r/with-let [hide-pay-tip (fn [e] (rf/dispatch [:doumi-use-vip-set-show-help false]))
show-tip (rf/subscribe [:doumi-use-vip-rmb-show-help])
icon-question (atom nil)
_ (-> js/document
.-body
(.addEventListener "touchend" hide-pay-tip false))]
[:span
{:style {:position "relative"
:margin-left (base 8)}
:color "#000"
:on-click (fn [e]
(let [element (r/dom-node @icon-question)]
(rf/dispatch [:doumi-use-vip-set-show-help (not @show-tip)])
(rf/dispatch [:doumi-style-set-pay-helper-qm-offsetleft
(-> element get-element-left)])
(rf/dispatch [:doumi-style-set-pay-helper-qm-offsetwidth
(-> element .-offsetWidth)])
(.stopPropagation e)))}
[:i#icon-question.icon.icon-question
{:ref (fn [com] (reset! icon-question com))}]
(when @show-tip [pay-tip-triangle])
(when @show-tip [pay-tip])]
(finally
(-> js/document
.-body
(.removeEventListener "touchend" hide-pay-tip false)))))
Hi, how can I prevent the (.submit some-form)
method to redirect my page to the form action url and keep the page still in the place I submitted the form? Just like in JS I can add a return false
in the function passed to the submit
method?
(defn logger-iframe []
(let [!ref (atom nil)]
(r/create-class
{:display-name "logger-iframe"
:component-did-mount (fn [] (some-> @!ref .submit))
:reagent-render
(fn []
[:form#logger-form
{:action logger-ext-url
:method "POST"
:ref (fn [com] (reset! !ref com))}
[:input {:type "hidden"
:name "userid"
:value ""}]])})))
If that's the case, forms have target
attribute that can reference an iframe. Although I've read somewhere that it was deprecated.
@cmal check the top answer: https://stackoverflow.com/questions/168455/how-do-you-post-to-an-iframe
Note that submitting on component-did-mount
looks like an anti-pattern to me. You should cause side effects based on user actions or browser events, not component lifecycles.
Are there any suggestions that can create an iframe
and POST
to another hostname and then dispose this iframe
, when the user click on somewhere on the page? We have a backend service running at our server(another hostname) to record the user actions.
@cmal I still think that it's something that could be done without iframes and forms, especially if you have the control of that server. E.g. I use Rollbar for basically the same task as you want to implement, and it doesn't create any forms.
The backend is not controlled by me, and the service is not used only by this page. In short, the backend service is not possible to be changed. I tried to proxy this host to my node service but my boss tell me not to do this, he want me to post to another hostname so the browser will not block the request when there are many. (It is said the browser can only deal with 8 request at the same time.) What is your suggestion? @p-himik
Doesn't something like https://www.html5rocks.com/en/tutorials/cors/ work in your case?
heya, trying to run reagent 0.7.0 on nodejs and allways getting ReferenceError: React is not defined
hello friends, I’m a bit of a n00b here, and I’m having trouble with a toggle function in this event listener https://gist.github.com/swlabrtyr/29d0fcd6a740a3807f4a6587e59955df if anyone can assist me in what I’m doing wrong I will be eternally grateful
@swlabrtyr it isn't working because you are recreating the local atom on every re-render https://gist.github.com/swlabrtyr/29d0fcd6a740a3807f4a6587e59955df#file-cljs-L14
@swlabrtyr Here is some reference info that should help https://github.com/reagent-project/reagent-cookbook/tree/master/basics/component-level-state
thanks @gadfly361!
I moved the let statement out of the function but the click handler still doesn’t do anything
the handler itself runs, as I am getting “test” statements in my dev console, but my note component’s local-state atom does not change
@swlabrtyr The code below should work and introduced the following changes:
1) persisting the local ratom (which we covered before
2) duplicate the arguments to render-note
in both the outher and inner functions
3) calling render-note
as a regent component (not as a function)
4) adding key metadata to prevent react warning
(defn toggle-class [a k class1 class2]
(println "test")
(if (= (@A K) class1)
(swap! a assoc k class2)
(swap! a assoc k class1)))
(defn render-note [text key]
(let [local-state (reagent/atom {:class "note note-off"})]
(fn [text key]
[:div {:key key
:on-click (fn [_]
(toggle-class local-state
:class
"note note-off"
"note note-on"))
:class (@local-state :class)}
(str text (@local-state :class))])))
(defn render-notes []
[:div {:id "notes-container" :class "notes-container"}
(doall
(for [n (range 1 65)]
^{:key n}
[render-note n n]))])
I included your code but it’s still not working… I think I should do some more reading, I didn’t know you could render hiccup with functions [render-note n n]
thanks for the help! I am probably missing something fundamental