There currently are two entry points to execute code in WebSharper. One is the control rendering mechanism. Since control rendering happens after the document has loaded, document "ready" event will not fire at this time. Another mechanism is using let-bound properties in modules, but as of 2.4 that code too executes after "ready" event.

Note that this makes it unnecessary to subscribe to "ready", just fire off your code from controls or modules.

Looking at your code, there are a number of problems with it. First and foremost, please clearly separate client and server code and use IntelliFactory.WebSharper.Html on the client and IntelliFactory.Html on the server. To call into client-side code from the server, use Web.Control control objects. Otherwise you are attempting to call into client-side code directly, which causes failure.

You also need to emit valid JSON (proper quoting) to get the jQuery callback to fire in your example.

Finally I use "OnAfterRender" to attach code to execute after the control has rendered, this is handy in many situations where the code must assume that DOM nodes have been already inserted into the document tree.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
namespace Website

open IntelliFactory.WebSharper

type Action =
    | Home
    | About

/// Hello World API client.
type HelloWorldData = { Message : string }

module Client =
    open IntelliFactory.WebSharper.JQuery
    open IntelliFactory.WebSharper.Html

    [<JavaScript>]
    let HelloWorld () =
        Div [Id "message"] -< []
        |>! OnAfterRender (fun self ->
            JQuery.GetJSON("HelloWorld", fun (data,_) ->
                self.Text <- data.Message)
            |> ignore)

[<Sealed>]
type HelloWorldControl() =
    inherit Web.Control()

    [<JavaScript>]
    override this.Body = Client.HelloWorld() :> _

module Server =
    open IntelliFactory.Html
    open IntelliFactory.WebSharper.Sitelets

    /// The hello world api.
    let HelloWorld : Content<Action> =
        CustomContent <| fun ctx ->
            {
                Status = Http.Status.Ok
                Headers = [ Http.Header.Custom "Content-Type" "application/json" ]
                WriteBody = fun stream ->
                    use tw = new System.IO.StreamWriter(stream)
                    tw.WriteLine "{\"Message\": \"hello, world!\"}"
            }
 
    /// A client page for the HelloWorld api.
    let Message : Content<Action> =
        Content.PageContent <| fun ctx ->
            {
                Page.Default with
                    Body =
                        [
                            H1 [Text "Message"]
                            Div [new HelloWorldControl()]
                        ]
            }

    let Main =
        Sitelet.Sum [
            Sitelet.Content "/" Home Message
            Sitelet.Content "/HelloWorld" About HelloWorld
        ]

    type Website() =
        interface IWebsite<Action> with
            member this.Sitelet = Main
            member this.Actions = [Home; About]

    [<assembly: WebsiteAttribute(typeof<Website>)>]
    do ()
By on 12/29/2011 1:13 PM ()

Thanks, Anton. My last comment was eaten by taking too long to submit it, so I was logged out. The gist was that I was curious when, if ever, one would ever use the

1
JQuery.Of(Dom.Document.Current).Ready(fun _ -> ...)

and how you would hook it up. As everything seems to need to be hooked up to some element, this function seems a little difficult to hook in correctly.

Less important, I thought it strange that I needed to wrap my control in a

1
Div []

when I already have a div element. Is there another container that wouldn't require unnecessary div nesting?

By on 12/29/2011 3:53 PM ()

You are right about JQuery "ready", does not seem to be useful in WebSharper.

By on 12/30/2011 12:47 PM ()

In order to get rid of the extra div you may upcast both the control and the H1 element to INode like this:

1
2
3
4
5
Body 
[
    H1 [Text "Message"] :> INode<_>
    new HelloWorldControl() :> _
]
By on 12/30/2011 4:31 AM ()

Ah, thanks for clarifying. I didn't follow the hierarchy far enough to see that Element implemented INode. Thanks!

By on 1/3/2012 8:57 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