Fork me on GitHub
#fulcro
<
2021-11-10
>
tony.kay02:11:01

For those of you using RAD: I'll be working on it in the coming weeks. There is a rad-1.1 branch on rad, rad-sui, and the rad-demo. I just pushed a form debugger, and the demo at the tip of that branch has a demo of that commented out in the account-forms AccountForm. Basically, it just leverages a combo of the RAD attribute info and the current state to show you a layout of all of the internals of the form's state, along with annotating things with notes/errors so you can see when something is going wrong.

🎉 6
❤️ 9
tony.kay02:11:33

detects things like cardinality errors, nils in idents, and uses the form's validator. ALso shows which fields are "complete" and therefore eligible for checking.

Jakub HolĂ˝ (HolyJak)18:11:35

ANN: This new video https://www.youtube.com/watch?v=rzK0_k5lzg4 explains and demonstrates how Fulcro walks the Root query and Client DB in parallel to produce the tree of data that will be passed to the Root component as its props when it is rendered. I hope it will help beginners understand better the query and "connectedness" of the data in the state. Feedback appreciated!

Jakub HolĂ˝ (HolyJak)21:11:14

@tony.kay Why does the following client DB lack the table + entry {:c/id {"A.A {:c/id "A.A" :c/n 1}}} ? What am I missing / doing wrong?

(tree->db
    (rc/nc [:p/id {:child [:c/id :c/n]}])
    {:p/id "A" :child #:c{:id "A.A" :n 1}})
; => {:p/id "A", :child [:c/id "A.A"]}

✅ 1
tony.kay21:11:21

3rd argument true

tony.kay21:11:37

otherwise the tables are in meta

tony.kay21:11:15

This is a very old function signature from Om Next. I have no idea why it was originally that way. Probably should make a newly named thing that is more plain to use

🙏 1
cjsauer22:11:13

Been staring at this for a while and can’t get it to work. Is something like this not allowed?

(defn expr-ident
  [props]
  (cond
    (contains? props :expr/id)       (find props :expr/id)
    (contains? props :levels-ref/id) (find props :levels-ref/id)))

(declare ui-expression)

(defsc Expression [this props]
  {:ident (fn [] (expr-ident props))
   :query (fn [] [:expr/id :levels-ref/id :expr/operator {:expr/operands '...}])})

(def ui-expression (comp/factory Expression {:keyfn (comp second expr-ident)}))
I keep getting Union components must have ident thrown within the tree->db function…as far as I can tell I’ve set up Expression with an :ident…I can’t seem to decipher the stacktrace.

Jakub HolĂ˝ (HolyJak)10:11:29

It would help to see the data tree you are passing to tree->db . From the code it seems it fails when normalize* calls itself here https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/normalize.cljc#L47 Here, sel will be the while query [:expr/id ...] and if v is a map, which I assume it is, then you run into https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/normalize.cljc#L17 and get the error. (EQL can contain maps at two places: either joins or union query under a join.) It would seem to me that you should be getting Expression's ident here. Could it be that props contain somethign that expr-ident does not handle and thus the cond returns its default nil ? Perhaps add :else (throw ...) to the cond to make sure that does not happen...

Jakub HolĂ˝ (HolyJak)10:11:57

This works fine for me

(tree->db Expression {:expr/id 1 :expr/operator 'inc 
                        :expr/operands [{:expr/id 2 :expr/operator 'dec 
                                         :expr/operands [{:levels-ref/id :leaf1}]}]} true)
so I'd really need to see your data.

cjsauer13:11:50

Thanks for the suggestion about expr-ident. That does indeed seem to be the culprit, but I’m still not sure why. It seems the props map being passed to expr-ident is empty, and that’s causing the cond to fall through. The data looks pretty much exactly like what you’ve tested above. Here’s a snippet above.

cjsauer13:11:11

I don’t think initial state would be relevant, because higher up in my component tree is a when block that prevents this part of the UI from rendering if the data isn’t yet available.

cjsauer13:11:11

I’m getting this ☝️ the expression doesn’t want to fully normalize. It stops after the first entity.

cjsauer13:11:56

(Oh you need to pass in true as the merge-idents argument to get the full result 😅

cjsauer13:11:27

So it seems I only get the error when I normalize from higher up in the component hierarchy…using tree->db on Expression seems to work fine. I imagine there’s something wrong elsewhere that I’m not seeing. Will keep searching. Thank you for taking a look and trying it out at the REPL!! The expr-ident hint was very helpful.

👍 1
Jakub HolĂ˝ (HolyJak)16:11:14

You got to me just when I was working with normalize :-)

cjsauer17:11:50

It’s a good omen 🙂

cjsauer22:11:55

Basically I have a recursive data structure in which branches have :expr/id , but leaves have :levels-ref/id

cjsauer22:11:59

Interestingly, from a normalized starting point, db->tree actually works…I see the expected tree structure. But trying to round-trip it with tree->db is complaining…

tony.kay23:11:38

If you're gettin an union error, then you have a union component with a map as a query...is that true?

tony.kay23:11:05

You MUST put an ident function on that component that works for any element the union might contain

tony.kay23:11:41

You're also doing something that seems very strange to me: You're making the table name change (first element of ident) for a single kind of component. That isn't going to work well for a union either...or is at least going to be confusing

tony.kay23:11:02

Also, find returns a MapEntry, not a vector...not sure if that matters. I've never tried using a MapEntry in app state

cjsauer00:11:47

MapEntry seems to work fine…I haven’t noticed any issues there.

tony.kay23:11:18

(cljs used to return vectors instead of MapEntry...but I think it returns MapEntry now...not sure)

cjsauer23:11:05

It seems that the {:expr/operands '…} is what it sees as the “union query”. Commenting that recursive join out “fixes” things. It is a pretty strange point in the data tree…I should maybe clean this part of my data tree up before even handing it to fulcro…

cjsauer23:11:19

It’s effectively a recursive union. Branch nodes are a different entity type than leaf nodes. Maybe I should create a top-level ExpressionNode component that encapsulates the union logic, and then separate BranchNode and LeafNode components for the two types of nodes.