2

I'm trying to get proper back-button support in my WebSharper-app. I can put stuff in history just fine:

type MyRecord = { foo: int; bar: string } 
JS.Window.History.PushState({foo=10; bar="hello"}, "", "mysuffix")

I was hoping to add a corresponding handler for onpopstate by doing something like this:

JS.Window.Onpopstate <- (fun e -> Javascript.Console.Info e.State.bar)

Unfortunately, this event has type Js.Window.Onpopstate : Dom.Event -> Unit and Dom.Event doesn't have a field State for getting back the state, even though the corresponding "real" Javascript event does.

How do I access state stored with PushState in the Onpopstate handler?

Søren Debois
  • 5,598
  • 26
  • 48

2 Answers2

2

You can access arbitrary fields from objects using the dynamic operator ?:

JS.Window.Onpopstate <- (fun e ->
    Console.Info e?state.bar
)

Note however that you still need to use [<Inline>] to call an arbitrary method.

Tarmil
  • 11,177
  • 30
  • 35
0

It turns out you can retrieve values from arbitrary Javascript like this:

[<Inline "$e.state">]
let stateOf (e : JavaScript.Dom.Event) = 
   Unchecked.defaultof<MyRecord>

I can now write my onpopstate handler:

JS.Window.Onpopstate <- (fun e -> 
  Javascript.Console.Info ((stateOf e).bar)
)

A caveat is that supplying nested records, class-type arguments, and Sets to PushState in general doesn't work. The browser is obligated to store only the JSON-serializable part of whatever you pass to PushState; and all the types just mentioned are implemented as Javascript objects.

Søren Debois
  • 5,598
  • 26
  • 48