Fork me on GitHub
#fulcro
<
2020-07-20
>
zilti10:07:43

I have a component with :route-segment ["tenant" :tenant-id] but the router won't accept it. I get "Spec failed. :tenant-id should satisfy string?". I have no clue why this happens. This is a valid route segment, and I use the same thing in other forms.

tony.kay15:07:59

@U2APCNHCN route segments are FORCED to strings (because they must be supportable from URLs which are strings). You’re probably passing a non-string to one of the functions that does routing, and it is warning you that you’ve used non-string data in routes.

zilti16:07:30

It doesn't even call the will-enter function though

zilti16:07:47

The routing works fine when using Fulcro's and Fulcro RAD's routing functions, but as soon as I want to access a parametrized page by URL, as in typing it in the address bar and pressing return, it falls apart

zilti16:07:11

Maybe some client middleware?

tony.kay16:07:28

take a look at other thread @U2APCNHCN

JAtkins12:07:42

Is the ident stringable? May be that issue, but I could be crazy

zilti12:07:59

You mean the component ident? That one is :tenant/id.

zilti12:07:45

But that shouldn't have any influence

dvingo15:07:19

are you trying to use (dr/change-route! ["tenant" "id here"]) ? can you post the stack trace?

zilti15:07:33

No, I am not. In fact it even happens when I am not using dr/change-route! at all. I am using dr/deferred-route!, but it clearly doesn't even reach that statement because the log/info I've put in front never gets executed. Here's the stack trace of the other form that also doesn't work for the same reason:

zilti15:07:47

Hmm actually the same happens for every form when I call the route directly as URL, instead of routing to it using dynamic-router

dvingo15:07:19

so it looks like a keyword is being passed to the router instead of a string

zilti15:07:10

Yes, apparently. Despite me doing it exactly as described in the book. And it works when routing from inside the app. The problem is accessing the route by URL (as in having the browser make the request "from zero")

tony.kay16:07:05

so it looks like your call to push-route! which is coming from html5 routing plugin ends up with a keyword at that location instead of a string. Ah, route history restores stuff form the URL params, and your URL has the keyword embedded in it for some reason

tony.kay16:07:32

so when you re-use that URL, it transit decodes the params in the URL and sends them, but they have invalid data in them for whatever reason

tony.kay16:07:02

Your problem is NOT on “load from scratch”, its somewhere where you’re setting paramters that get saved in the URL (all controls on the form/report)

zilti16:07:24

Well when I go to the URL it clearly isn't embedded in the URL

zilti16:07:36

Yet I still get that error

zilti16:07:19

This is what my fix-route looks like:

(m/defmutation fix-route
    "Mutation. Called after auth startup. Looks at the session. If the user is not logged in,
     it triggers authentication"
    [_]
  (action [{:keys [app]}]
            (hist5/restore-route! app ui/Root {})
            ))
Maybe the problem is there?

tony.kay16:07:55

wait…that URL is the route?

tony.kay16:07:24

where’s the ID you mention in the route segment?

tony.kay16:07:34

you said tenant I thought

zilti16:07:33

Yes, I made two forms like that, and both fail. Actually all fail

tony.kay16:07:59

So, clearly I should have better error messages in the routing code, but if it is giving you errors related to a different route then: 1. Your “default route” might be the tenant one, which will fail because no params are possible on init 2. The URL you’ve given has no legal match, so it is doing something unexpected…

tony.kay16:07:18

but your URL says nothing about tenant

tony.kay16:07:33

it says “reset-password”

zilti16:07:50

Yes, the other one is

tony.kay16:07:35

and you can directly call change-route! on ["tenant" "1"] and it works?

zilti16:07:23

Rather, I currently use rroute/route-to

zilti16:07:43

I have more, same goes for :route-segment ["vendor" :vendor/id], it works fine with (rroute/route-to! this VendorDetailView {:vendor/id whatever-the-id-is}) but http://localhost:3000/vendor/whatever-the-id-is will fail, even though that is what ends up being in the address bar after the route-to!.

zilti22:07:16

Ah, I tried it in Firefox and can actually see it change the URL to one where it includes the keyword when calling the URL with the browser.

zilti22:07:58

It changed from to .

tony.kay05:07:13

strange…I’d have to go back through the code. Not sure what’s going wrong there. It is working fine in my apps, and in the demo.

zilti11:07:52

Hmm. I will also look through mine as well. Might be something with how I redirect after checking if the user is logged in. That turned out to be a massive mess to do with all the async that is going on

zilti11:07:25

In all fairness, I am currently afraid to touch that part

tony.kay15:07:16

yeah, that’s why I use a UISM for login..and when you mix in html5 history support things get interesting if you don’t keep it really clean

zilti15:07:41

UISM is actually what I use for login. I copied the one from the fulcro template

tony.kay15:07:41

so where is your extra async? Or you mean you have not taken the time to understand what is there?

zilti16:07:46

Well, first I have to make sure my program waits until the UISM has figured out if the user is logged in or not, and then it has to check if the user is allowed to see the requested page depending on the session map the UISM fetched, and then do a redirect if not; but also, if and only if the user is on the landing page it has to redirect to whatever is the actual landing page for the user role.

tony.kay16:07:21

right, so it sounds like perhaps you should have a flag that prevents all rendering (on root) until all that mess is figured out, and probably does not install history event listeners until you’ve got that as well.

zilti13:07:04

Okay I created another new form with a route segment with a keyword and get the same error as well...

magra15:07:44

My route segments are either ["person-list"] or ["person" :person/id] in the first case my :ident is a function (fn [] [:component/id :person-list]) and in the latter it is :person/id .

dvingo15:07:45

I have a top level property in my app db that I want to load a collection of idents into, but I want the load to but cumulative (issuing multiple loads should append data and not clear the vector) - when I issue a df/load! that targets that top level property the data from the load overwrites the collection that is there - using target append-to does not work either. Is this a supported use case or will I have to use a mutation and handle the merge logic myself?

tony.kay16:07:58

what do you mean “`append-to` does not work either”? Ah, append-to might to for to-one only. I would consider that an oversight…I’ve never used it for that. I’d accept a PR for a check in append-to that would do collections I guess. Your option right now is just to make it a post-mutation of your own. Ultimately, that’s all data targeting is.

dvingo17:07:19

yep - it's a collection of idents - I will try out the post mutation option for now and may look into updating the data targeting to support that.

magra15:07:54

@danvingo I do that with append-to.

magra15:07:52

It works but can cause duplicate entries when appending.

lgessler22:07:03

The fulcro docs for form state have this example input:

(dom/input {:value    (or name "")
            :onBlur   #(comp/transact! this [(fs/mark-complete! {:entity-ident [:person/id id]
                                                                 :field        :person/name})
                                             :root/person])
what's the :root/person doing in the transaction?

jb recluse02:07:15

i think @danvingo correctly described its function below. as additional info, the book appears to call it a "follow-on read" if i understand correctly. http://book.fulcrologic.com/#_historical_note_on_older_approaches http://book.fulcrologic.com/#_combining_routing_with_data_management

tony.kay05:07:42

Yes, that’s it exactly. The original rendering model asked the user for hints on “dependent refreshes”. These are still allowed and rendering can still use them (ident-optimized), but the current best practice is to use a renderer that doesn’t need the help.