Fork me on GitHub
#clojurescript
<
2019-06-27
>
fadrian00:06:16

I have a reagent application. I want to use hiccup to generate some html, which is then displayed to the user. As such, I want to use hiccup's html call to get the html from the hiccup forms. To do this, I added [hiccup "1.0.5"] to my project dependencies in project.clj and [hiccup.core :refer [html]] to the require clause of my ns definition as so: (ns http://cql-viewer.app (:require-macros [cljs.core.async.macros :refer [go]]) (:require [reagent.core :as r] [cljs.core.async :refer [<!]] [cljs-http.client :as http] [hiccup.core :refer [html]] )) But when I try to evaluate the ns form, I get an error: "clojure.lang.ExceptionInfo: No such namespace: hiccup.core, could not locate hiccup/core.cljs, hiccup/core.cljc, or Javscript source providing "hiccup.core" in the file <directory name>." I'm wondering why the module hiccup.core is not being found in the project where I've included hiccup in my project dependencies. And, for those who are curious, here's the :dependencies clause from my project.clj file: :dependencies [[org.clojure/clojure "1.9.0"] [binaryage/devtools "0.9.4"] [org.clojure/clojurescript "1.10.238" :scope "provided"] [reagent "0.7.0"] [cljs-http "0.1.46"] [hiccup "1.0.5"] ]

dpsutton01:06:01

Hiccup is a clj not cljs lib

fadrian01:06:24

Crud. I hadn't thought about that. Is there any way to do what I want to in Clojurescript? Turn hiccup into html outside reagent?

dpsutton01:06:49

Can’t you just r/render? Seems exactly what reagent does. Takes hiccup to html right?

☝️ 4
fadrian02:06:31

Didn't know about the r/render call. I'll try that.

vinurs04:06:02

in cljs, there without :refer :all ?

fadrian07:06:48

I ended up grabbing the rendered HTML into a string by getting the value of the node's innerHTML attribute post-render. It seems to work.

Alan Thompson13:06:46

@haiyuan.vinurs Corrrect. CLJS does not have :use or :refer :all

Olical16:06:04

I'd say this is a very good thing 😅

👍 4
mfikes14:06:41

@cloojure FWIW, ClojureScript does have :use, but you must also supply :only

Alan Thompson15:06:43

Oh, right. With CLJ, I only use the "unlimited" version of :use as a more explicit synonym for :refer :all

fadrian20:06:54

I've got the following Clojurescript/reagent code: (defn generate-id [] (str (gensym))) (defn atom-backed-textfield [id value] [:input {:id id :value @value :type "text" :on-change #(reset! value (-> % .-target .-value))}]) (defn codeable-concept [obj] [:div (atom-backed-textfield (generate-id) (:code obj)) (atom-backed-textfield (generate-id) (:family obj)) (atom-backed-textfield (generate-id) (:display obj))])

fadrian20:06:29

And in my render method, I'm calling codeable-concept like this: (codeable-concept {:code (r/atom "123") :family (r/atom "CPT") :display (r/atom "A value set")})

fadrian20:06:05

The three widgets appear on the screen with their correct values, but when I type in any of the text boxes, the values of the atoms don't change. I've put log statements in the :on-change function, so I know that 's being called and passed the proper value for the atom to be set to. It just appears as if value's value is not being captured properly because the reset! seems to have no effect on my atoms. Any ideas?

danieroux21:06:46

Have a weird advanced compilation issue: I get TypeError: L is not a function - which makes sense, because window.L is https://leafletjs.com How do I make Google Closure not use L as a minified variable?

mfikes21:06:14

@danie The general technique is to either explicitly provide externs or have externs be inferred

mfikes21:06:18

(Externs inference is probably the better way to go these days, FWIW.)

danieroux21:06:34

@mfikes I am inferring externs, and Vega, React and Amplify is all working well and happily. It’s just this Leaflet magic L that clashes. Some minified function calls it, and gets upset:

dnolen21:06:11

@danie did you use :output-wrapper to prevent clashes?

danieroux21:06:57

@dnolen no, thank you for the pointer

dnolen21:06:10

it puts compilation output in a closure to avoid clobbering other globals

danieroux21:06:09

@dnolen that solves it, thank you!

mfikes21:06:49

@fadrian Reagent uses a special implementation of atoms to know when to re-render. Are you using Reagent atoms or ClojureScript atoms?

mfikes21:06:58

Oh, sorry; I see you are.

mfikes21:06:43

What’s that code trying to do? Is it resetting to the same value?

fadrian21:06:44

I'm using reagent atoms. Is there a special r/reset! I should be using

mfikes21:06:58

I’m AFK, but I thought they implemented IAtom

fadrian21:06:05

Yes, ultimately, as characters are typed in the text box, the atom that is passed in is supposed to be updated to what's typed. I'm thinking that this is something else. When reagent re-renders, I assume that the render functions are called again, correct?

fadrian21:06:58

If that's so, then each time I re-render, I'm creating three new atoms (in codeable-concept) with their original values and re-rendering the three widgets with those values, making it look as if nothing I type is captured.

fadrian21:06:17

Does that sound reasonable?

mfikes21:06:21

Yeah, that sounds reasonable

fadrian21:06:14

Well, I am new to Clojurescript - I'm not yet certain as to where to place all the moving parts. I guess I'll figure it out by the time I'm done with this.

mfikes21:06:11

I’ve pretty much stuck with the “one global atom” approach and never bothered to learn about the case you present above

lilactown21:06:38

@fadrian reagent allows you to return a closure, instead of hiccup data, in order to maintain local atom state across re-renders

lilactown21:06:50

ex:

(defn my-component []
  (let [state (r/atom "I will persist state across re-renders")]
    (fn []
      [:input {:on-change #(reset! state (.. % -target -value)) :value @state}])))

fadrian21:06:43

Yeah. I see how that would work. I'll try something like that.

lilactown21:06:51

on initial render, the whole my-component function will be run and then the returned anonymous function as well, to get the initial DOM. for subsequent re-renders, it will just re-run the anonymous function

lilactown21:06:13

it’s a special reagent idiom called a “form-2” component

fadrian21:06:12

Oh yes, I remember reading about those now. There are also form-1 (the normal, return hiccup form), and form-3 (which no one usually ever uses).

fadrian21:06:59

It's been a while since I last tried to absorb cljs and it's been a while since I found references to those.

fadrian21:06:39

I'm glad I finally figured out what they were talking about...

fadrian21:06:17

Thanks for your help.