question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handle page models in Router.infer

See original GitHub issue

The problem: we have an application with several pages that are routed via Router.infer. We would like to keep a piece of model that is specific to the current page. For example, say /counter has a model of type Counter.Model, /data/{dataId} has a model of type Data.Model, and / and /hello/{name} have no specific model. We don’t want to keep all these models side by side in the global app model and have to juggle their behavior when switching pages; instead, we want to only have the model relevant to the current page.

Currently, the only solution to this problem is what @kunjee17 shows in #78: defining a separate union for the model, with a case for each page that needs one. This means a bunch of boilerplate with partial matching at every use site, which is far from ideal.

Instead, we should be able to include the page route and model together in the same union. For example with something like this:

type Page =
    // A page can have no model...
    | [<EndPoint "/">]
      Home
    // ... or just a page model...
    | [<EndPoint "/counter"; PageModel "counter">]
      Counter of counter: Counter.Model
    // ... or just path arguments...
    | [<EndPoint "/hello/{name}">]
      Hello of name: string
    // ... or both.
    | [<EndPoint "/data/{dataId}"; PageModel "data">]
      Data of dataId: int * data: Data.Model

The inconvenient would be that when using router.Link, you need to pass something as the model (presumably Unchecked.defaultof<_>, which we might alias for convenience).

A question that needs to be resolved is how to handle the case when the page is set from the URL. This happens on page startup, and when the user clicks a link. We generate a Page value from the URL, but that means that we need to have a “default” model value to fill that field in. A possibility would be to provide it as an extra argument to Router.infer like this:

let defaultPageModel = function
    | Counter _ -> box Counter.defaultModel
    | Data _ -> box Data.defaultModel
    | Home | Hello _ -> null

let router = Router.inferWithModel SetPage (fun model -> model.page) defaultPageModel

Bolero would call this function once per case with a dummy Page just to get the corresponding default model. Unfortunately this function has to return obj, since each case can have a different type of model (or none at all). I would love suggestions on how to make this better typed! (without switching to a dependently-typed language 😄)

If the app needs more specific handling (for example, if the user is on /data/1 and clicks a link to /data/2, should we keep the existing page model or reset it to the value from defaultPageModel?), it can be done in the update function’s handling of SetPage.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
BentTranbergcommented, Sep 11, 2019

I have the same problem/question in my applications that use Elmish.WPF. It would be nice if a solution could be found using Elmish, at least kind of partially, but I understand that could be a tall order.

0reactions
vip-ehowlettcommented, Jul 14, 2022

That seems to be exactly what I was looking for. Thanks for the help!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Routing - Bolero: F# in WebAssembly
Routing. Bind the page's URL to the Elmish model. ... The easiest way to create a router is by using an inferred router....
Read more >
Inferring router ownership based on the classification of intra
In summary, this paper proposes a router ownership inference method based on the classification of intra- and inter-domain links. The main idea ...
Read more >
Routing: Pages and Layouts
Create your first page and shared layout with the Pages Router. ... The React model allows us to deconstruct a page into a...
Read more >
Azure Machine Learning inference router and connectivity ...
Azure Machine Learning inference router handles autoscaling for all model deployments on the Kubernetes cluster. Since all inference ...
Read more >
On Inferring Autonomous System Relationships in the ...
We classify the types of routes that can appear in BGP routing tables based on the relation- ships between the ASes in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found