This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-23
Channels
- # aleph (1)
- # architecture (4)
- # aws (7)
- # beginners (249)
- # boot (17)
- # calva (4)
- # cider (30)
- # cljdoc (7)
- # cljs-dev (1)
- # cljs-experience (3)
- # clojure (69)
- # clojure-dev (7)
- # clojure-europe (1)
- # clojure-italy (7)
- # clojure-japan (15)
- # clojure-spec (6)
- # clojure-uk (39)
- # clojurescript (51)
- # cursive (31)
- # data-science (4)
- # datavis (1)
- # datomic (40)
- # dirac (67)
- # duct (8)
- # editors (15)
- # emacs (9)
- # events (3)
- # figwheel-main (2)
- # fulcro (157)
- # juxt (4)
- # kaocha (11)
- # lein-figwheel (1)
- # off-topic (31)
- # pathom (18)
- # re-frame (4)
- # reagent (2)
- # reitit (16)
- # remote-jobs (1)
- # shadow-cljs (11)
- # specter (2)
- # speculative (1)
- # tools-deps (27)
- # vim (1)
- # yada (2)
unrelated question to the above but still trying to clarify how validation in a form works. I have form fields declared in my component, the same form fields are reflected in the query/initial state. my component has an ident as well. for whatever reason, calling (fs/get-spec-validity props)
returns :valid
despite none of the fields being marked as complete.
@mss I use the form state stuff regularly. It works. Are you remembering to add form config?
Are you following the book, or just doc strings? There are tons of examples with full source in the book.
I’m following the book. I was under the impression I was doing it correctly but clearly something is off. have the form-config-join
added to my query
per the examples and book if something isn’t complete, it should be :unchecked
. somehow getting a :valid
result for my component’s props despite not calling mark-complete
Looking in inspect, do you have a valid ident pointing from the instance’s form join to a real form config in state?
the functions cannot work properly if the config isn’t present. Could use better console error messages around that, if you’re not getting any
unfortunately working in an electron app and haven’t gotten the inspector to work with it
which MUST be run to initialized the form config on any instance that acts as a form (via a mutation, e.g.)
ah I was under the impression that add-form-config was only used when you wanted to integrate a newly generated ident whether on the client/server
gotcha, that def makes sense. so a call in the containing component would look like: :my-form-data (fp/get-initial-state (fs/add-form-config MyForm [:forms/by-id :my-form) {})
?
I always do it in mutations…but I think that function returns the tree for the component with the tree added…so it would be:
(defsc X [_ _]
{:initial-state (fn [params] (add-form-config X [:x/by-id 22] {:id 22 :x/name "boo" ...})
I’ve not build an electron app…is there any way to just build stuff in workspaces, and then combine the bits into the electron app? That would make life a lot better.
ehh for bits and pieces yes but for certain things it’s basically impossible to work on sans an electron app. the fulcro-inspect has some code related to remote inspection and a client side script to start a server and broadcast changes. when I get some time I should take a crack at extending that and getting it working, would sidestep the whole issue
sandboxed webviews for third party content. the implementation is a little different on electron vs just an iframe
I should just pull these other bits out and work on them in an actual browser, you’re absolutely right 😝
@tony.kay Hello 🙂 I have a very specific question on error handling with Fulcro. I am trying to catch API requests that respond with 401 and, when it happens, redirect to some route. I read through the Fulcro book and it seems like the simplest way to do this would be to set a :network-error-callback
. I did so, but it doesn’t seem to be triggered. Here’s my code:
(defn error-handler [state status-code error]
(log/warn "Global callback:" error " with status code: " status-code))
(defn ^:export init []
(reset! SPA (fc/new-fulcro-client
:network-error-callback error-handler
...
and the console output: https://puu.sh/CBatW/67a402b2e1.png@hmaurer not off the top of my head. The networking is involved (e.g. the remote you’ve configured)…if you used custom networking I think that might be able to break it.
Ah. I didn’t make any changes to the networking from the lein template:
(defn ^:export init []
(reset! SPA (fc/new-fulcro-client
:network-error-callback error-handler
:started-callback (fn [elogic-beyond]
(df/load elogic-beyond :all-users root/User))
;; This ensures your client can talk to a CSRF-protected server.
;; See middleware.clj to see how the token is embedded into the HTML
:networking {:remote (net/fulcro-http-remote
{:url "/api"
:request-middleware secured-request-middleware})}))
(start))
says right in the doc string “Only works if you choose to use the default built-in networking (ignored if you also specify :networking).”
Ah, I see, sorry! I thought I was using the built-in networking and missed the “ignored if you specify :networking”
I just tried the middleware approach; it works perfectly except for one thing: is there a way to write an async middleware? i.e. I would like to trigger the redirect but return the equivalent of a promise that doesn’t resolve, so Fulcro “hangs” (as if the request was still in flight) until the redirect completes
what you’re saying doesn’t make sense in the context of Fulcro. The rendering/interaction is purely a function of what you’ve rendered. The network layer is about moving data from the network INTO that state…so, what you want to do is end up with the correct state to show what you want…“hang” isn’t a thing.
You can change the tx and body of the response (where tx is the query used for merge)…THUS middleware can cause any change to app state imaginable
If you want to make a “pessimistic mutation” (e.g. cause a tx that is processed in steps) then that is a higher level abstraction, not a network one, in Fulcro
but then you haven’t actually described the feature….I’d assumed what you wanted was something that would cause a UI error on network errors in a “general way”…you can handle that in a bunch of ways: 1. Save the reconciler in a global place, and add a network layer hook that transacts against it (in a deffered (setTimeout) way) 2. Do middleware transform of tx and body to cause a merge of state with the app that will show a blocking dialog 3. Write you own custom network layer…heck, you could even call js/alert in it if you want 4. A custom networking object can indicate that is supports progressive updates as well, which means it can cause a merge (via the update callback) at any time to change the UI…it’s how file upload progress works in file upload remotes.
@tony.kay thanks for the detailed reply. This isn’t quite what I meant, though. What I was wondering is whether there was a way, through a middleware (or similar), to tell Fulcro that the request was still in flight. An async middleware, basically. Perhaps i am thinking about this wrong though, I’ll look into what you mentioned.
you can implement that by setting a flag, running a pess. tx, and having the flag be unset after a step completes
@tony.kay I see, but doesn’t my use-case make sense? Here’s the middleware I wrote (really dumb):
(defn auth-response-middleware [response]
(if (= 401 (:status-code response))
(redirect! "/sign-in"))
(net/wrap-fulcro-response response))
The issue I was trying to get around is that the redirect (through window set location) takes some time, and in that time Fulcro is going to process the response and the UI might flicker a little bitso you’re asking me “is there a way to prevent the processing of the response” I think
@tony.kay yes. I found it easier to implement my auth flow outside of Fulcro, so I can just put all API requests behind an auth check (instead of trying to let some API requests, through, i.e. auth requests)
basically Fulcro trusts the middleware to tell it “what was asked for, and what is the response”…if you say nothing and nothing, then…nothing
@tony.kay ah perfect, thank you. I should have formulated my question better; that’s what I was looking for
@tony.kay like this? (assoc ((net/wrap-fulcro-response) response) :transaction [] :body {}))
. Or straight up on the response?
technically, on non-200, it returns what we want…so you you original should have worked 😕
@tony.kay unrelated but while working with the new lein template I stumbled upon a bug with Hiccup 1.0.5 when you use dot classes in conjunction with dynamic classes, i.e. [:div.foo {:class (if error "has-error)}]
. I asked weavejester and the bug has been fixed in Hiccup 2 alpha 2 (although I found another bug in that version for which I have yet to file an issue). Would you accept a PR on the lein template to upgrade to Hiccup 2 alpha 2?
Quick q: what is the syntax/approach with Fulcro to “combine” queries of components? i.e. if a component renders two sub-components that each need to display “person” data, can I compose the queries of the two sub-components into the parent component?
And likewise, when using df/load
, can I merge the queries of more than one component?
normalization requires that queries by properly annotated with component metadata, which get-query does
but in general you just issue multiple loads…they get combined into one network request if they are submitted together
and yes, you can of course compose them into a parent (under unique keys)…not sure what you mean there @hmaurer
“compose” was poor wording. What I meant was basically merge. What if the parent wants to display two child components each requiring different “person” data from the spouse?
the naive approach would be using into
, which won’t work. Is there a non-naive approach?
(I am basically looking for an equivalent to graphql fragments. You have two sub-components that each want some fields from a “user”, and the parent component has to specify that it requires the union of the fields of all its sub-components)
(defsc Parent [this props]
{:query [{:spouse (prim/get-query Person) :children (prim/get-query Person)}]}
BUT this is definitely *NOT*:
(defsc BadParent [this props]
;; NEVER do this
{:query (fn [] (into (prim/get-query A) (prim/get-query B)))})
yep, I think Pathom’s author mentioned metadata being associated to queries in his conj 2018 talk… which is why I was wondering how it could be done (since simply using into
wouldn’t work)
but this is fine:
(def shared-props [:x :y])
(defsc A [_ _]
{:query (fn [] (into shared-props [:z]))})
(defsc B [_ _]
{:query (fn [] (into shared-props [:b]))})
which is very different from before, because the earlier one was losing the distinction (and normalization info) between A/B as normalized components
(defsc X [_ _]
{:query (fn [] (into [:a :b] (zipmap [:spouse :children :best-friend :work-buddies] (repeat (prim/get-query Person)))))})
this is fine because it’s just another way of writing a legal query: [:a :b {:spouse (prim/get-query Person)} ...]
FYI, get-query
essentially returns (with-meta [:x] {:component X})
for a component X with query [:x]
…nothing that special
Oh, that’s good to know. Also I was being silly, I think I just realised what I am asking might be the :>foo
feature Pathom’s author talked about at conj. I am not sure what the name is
but if I recall correctly it stays within the same resolution “context” but allows nesting, so you can fetch data for multiple components
so am I correct in thinking that’s basically the solution to the “merging” issue? You can’t “merge” queries of child components because of the issues you described above, but you can use placeholders to achieve a similar result
Channel: So, I’ve been thinking that once a week I might be able to do something like a “group Q/A” via some kind of screen sharing service (YouTube? Twitch? Not sure what option would be best). This would be a paid attendance sort of thing, but the ideal would be for it to be like a coding dojo where we could share code/tips/etc. on Fulcro. Any interest?
It depends on the format / content / cost, but overall I would be interested and would definitely attend the first one if it’s at a reasonable GMT hour 🙂
Also I would be particularly interested if there is a focus on architecture / design.
Twitch recently made changes that would make this a lot easier. Not necessarily advocating for it, just saying that they added a lot of new categories, and streaming to twitch is an absolute breeze. It’s also far more interactive than YouTube. I would be happy to help you both get that set up, and stream it.
I was thinking in the $10-20/person range. Not sure the format though…I’d have to give it more thought. Might be a good way to motivate me to build some more demo apps that we can share, but in collaboration with you all so I’m hitting “sore spots”
Does twitch do shared audio with the group, or just one-way. I’m guessing participant count would be quite low, so audio for everyone would be best
If you wanted multiple participants, you can use something like discord or any other voice app. Then use that as an audio source for OBS.
Twitch for the first one, where you build a Fulcro application with WebRTC, that we then use in the following weeks? 😄
This is a great idea. I’d also recommend recording the sessions since your users are spread across so many time zones.
Something like these sessions would be perfect since I don’t yet use Fulcro professionally and can’t devote nearly the time I want towards learning/working with it. Plus, anything the community can do to keeping you working on the library is a big plus!
@tony.kay do you have a date for a first one of these? or is it still at the idea stage?
looking at level of interest…doesn’t make too much sense if there are not at least 5-10 ppl interested
What level of instruction are you thinking? Deep dive into advanced features, or building an understanding from the ground up (wondering if I should invite non-Fulcro users whom I hope to convert). Both are great.
I’m game, based on interest, to narrow the topic per session to whatever there is interest in. “How do I do X?” is what I was thinking…perhaps participants submit in advance, and each gets a 10-minute dive (or n-times that if there are n interested parties interested in it). I’m open to format.