Although for your use case, I would probably use local storage instead of cookies, see an example here.

By on 11/26/2015 10:56 AM ()

Thanks. I've written a simple helper to automatically store/restore Var<string> values:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[<JavaScript>]
module Option =
    let getStringOrEmpty (x: string option) = 
        match x with
        | Some x -> getOrEmptyStr x
        | None -> ""
        
[<JavaScript>]
module LocalStorage =
    let get (key: string): string option =
        let storage = JS.Window.LocalStorage
        let value = storage.GetItem key
        if value = null || value = JS.Undefined then None
        else Some value

    let set (key: string) (value: string) =
        let storage = JS.Window.LocalStorage
        storage.SetItem(key, value)

[<JavaScript>]
module View =
    let ofVarPersistent (name: string) (var: Var<string>) =
        var.Value <- LocalStorage.get name |> Option.getStringOrEmpty
        var.View |> View.Map (fun x -> 
            LocalStorage.set name var.Value
            JS.Alert (sprintf """Set "%s" = "%s" """ name var.Value) // <------------
            x)
let vFilter = Var.Create ""
let _ = vFilter |> View.ofVarPersistent "filter"

// the rest of code...

The problem is that the alert does not pop up and the value does not appear in Local Storage in Chrome's F12. What may be the problem? Is it inability to invoke JS from whithin View.Map or the fact then the view is not used anywhere?

By on 11/27/2015 12:13 AM ()

To avoid memory leaks the map function of a view only gets called on updates if the resulting view is inerted into the DOM down the road. So if you want to do side-effects in a View.Map you have to map it an empty doc (Doc.Empty) and insert that into the DOM with Doc.EmbedView. The lifetime of the view will then be tied to the lifetime of the corresponding dynamic node. E.g. if you have something like a conditional rendering of some element based on a view, and you insert your empty Doc into the conditionally rendered tree your view will only be updated if the empty document should be rendered (so when the condition holds).

By on 11/27/2015 4:05 AM ()

Thanks for the explanation. So the following code works ok, but is rather ugly

1
2
3
4
5
6
let vFilter = Var.Create (LocalStorage.get Filter.StorageKey |> Option.getStringOrEmpty)
let vFilterMatcher = 
	vFilter.View 
	|> View.Map (fun x ->
		LocalStorage.set Filter.StorageKey vFilter.Value
		Filter.parse x)

What about adding a callback which would be 100% called whenever the value of Var changed Var.Create "initial value" (fun newValue -> ...)? I understand that it does not fit into Var -> View archetecture.

By on 11/27/2015 4:43 AM ()

Alteratively you could use the lens functions of vars to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Var with
    static member CreatePersistent (key : string) (defValue : 'T) =
        let storage = JS.Window.LocalStorage
        let v = storage.GetItem(key)
        let va = 
            if v ==. null then Var.Create defValue
            else Var.Create <| As<'T>(JSON.Parse(v))
            
        va.Lens id (fun _ b -> 
            storage.SetItem(key, JSON.Stringify(b))
            b)

let Main =
    let foo = Var.CreatePersistent "foo" ""
        
    Doc.Input [] foo
    |> Doc.RunById "main"
By on 11/30/2015 1:42 AM ()

I tried your function and the whole client side does not work now :( Reverted Var.CreatePersistent to Var.Create and v.Set "" to v.Value <- "" and everything works OK.

I suspect Lens and IRefs cannot be used on client side, can they?

By on 12/1/2015 6:29 AM ()

They should work on the client-side as they have only a client-side implementation currently. What error do you exactly get? This piece of code worked as expected for me.

By on 12/1/2015 9:02 AM ()

I tried your code in a hello world project and it works.

I suspect the JS code crashed trying deserialize old value, written as pure String, not as JSON.

By on 12/2/2015 9:51 AM ()

Good point, we are adding a binding to a small cookie library, tracking here.

By on 11/26/2015 10:55 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper