Skip to content

Instantly share code, notes, and snippets.

@o1lo01ol1o
Last active February 24, 2017 16:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save o1lo01ol1o/6955b9c23f007ee17a6e3431b8dab160 to your computer and use it in GitHub Desktop.
Save o1lo01ol1o/6955b9c23f007ee17a6e3431b8dab160 to your computer and use it in GitHub Desktop.
websharper jquery listeners in client-server templates
namespace Testest
open WebSharper
open WebSharper.JavaScript
open WebSharper.UI.Next
open WebSharper.UI.Next.Client
open WebSharper.UI.Next.Html
open WebSharper.JavaScript
open WebSharper.JQuery
[<JavaScript>]
module Client =
[<Direct "new Awesomplete($input)">]
let awesomplete input = X<unit>
type JQuery with
[<Inline "$this.select2()">]
member this.Select2() = X<JQuery>
// Workaround for https://github.com/intellifactory/websharper/issues/639
[<Inline "new Event($name)">]
let NewEvent (name: string) = X<Dom.Event>
let personName = Var.Create "Bob"
let personName2 = Var.Create "Abe"
let Main () =
let cls s = attr.``class`` s
let data a b = attr.``data-`` a b
let opts = Var.Create (Some [""; "Abe"; "Andrew"; "Bill"; "Bob"; "Joe"; "Rex"])
div [
div [
h4 [text "Awesomplete"]
div [
Doc.Input
[
attr.id "auto-complete"
data "list" "Abe,Andrew,Bill,Bob,Joe,Rex"
data "minchars" "0"
on.afterRender (fun el ->
JQuery(el)
.On("awesomplete-selectcomplete", fun el ev ->
el.DispatchEvent(NewEvent("change")) |> ignore)
.Ignore
awesomplete el)
]
personName
p [text "This input works correctly when typing - text is reactively updated below - but fails when selecting from the autocomplete options."]
]
hr []
h4 [text "You entered"]
div [
textView personName.View
]
br []
br []
br []
br []
hr []
h4 [text "Select2"]
div [
opts.View
|> View.Map (fun op -> match op with
| Some o ->
Doc.Select [
on.afterRender (fun e ->
JQuery(e)
.Select2()
.Change(fun el ev ->
if not (JS.HasOwnProperty ev "originalEvent" && ev.OriginalEvent?uinext) then
let domEv = NewEvent("change")
domEv?uinext <- true
el.DispatchEvent(domEv) |> ignore)
.Ignore
)
] id o personName2
| None -> div []
) |> Doc.EmbedView
]
hr []
h4 [text "You entered"]
div [
textView personName2.View
]
]
]
namespace Testest
open WebSharper
open WebSharper.Sitelets
open WebSharper.UI.Next
open WebSharper.UI.Next.Server
type EndPoint =
| [<EndPoint "/">] Home
| [<EndPoint "/about">] About
module Templating =
open WebSharper.UI.Next.Html
type MainTemplate = Templating.Template<"Main.html">
// Compute a menubar where the menu item for the given endpoint is active
let MenuBar (ctx: Context<EndPoint>) endpoint : Doc list =
let ( => ) txt act =
liAttr [if endpoint = act then yield attr.``class`` "active"] [
aAttr [attr.href (ctx.Link act)] [text txt]
]
[
li ["Home" => EndPoint.Home]
li ["About" => EndPoint.About]
]
let Main ctx action title body =
Content.Page(
MainTemplate.Doc(
title = title,
menubar = MenuBar ctx action,
body = body
)
)
module Site =
open WebSharper.UI.Next.Html
let HomePage ctx =
Templating.Main ctx EndPoint.Home "Home" [
h1 [text "Say Hi to the server!"]
div [client <@ Client.Main () @>]
]
let AboutPage ctx =
Templating.Main ctx EndPoint.About "About" [
h1 [text "About"]
p [text "This is a template WebSharper client-server application."]
]
[<Website>]
let Main =
Application.MultiPage (fun ctx endpoint ->
match endpoint with
| EndPoint.Home -> HomePage ctx
| EndPoint.About -> AboutPage ctx
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${title}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
<style>
/* Sticky footer styles */
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
height: 60px;
background-color: #f5f5f5;
}
.container .text-muted {
margin: 20px 0;
}
</style>
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.1/awesomplete.css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
</head>
<body>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Your App</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav" data-hole="menubar"></ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="http://websharper.com">websharper.com</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div data-replace="body">
</div>
</div>
<footer class="footer">
<div class="container">
<p class="text-muted">
For an enhanced template that provides automatic GitHub deployment to Azure, fork from <a href="https://github.com/intellifactory/ClientServer.Azure">GitHub</a>, or
read more <a href="http://websharper.com/blog-entry/4368/deploying-websharper-apps-to-azure-via-github">here</a>.
</p>
</div>
</footer>
<script data-replace="scripts"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.1/awesomplete.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
</body>
</html>
<configuration>
<appSettings>
<add key="WebSharper.JQuery.Resources.JQuery" value="http://code.jquery.com/jquery-3.1.1.min.js" />
</appSettings>
<!-- NOTE: comment the following to run on F# 3.0 -->
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<!-- NOTE: remove debug="true" to serve compressed JavaScript -->
<compilation debug="true" targetFramework="4.0" />
<!-- This is only needed for VS Development WebServer. IIS/IIS Express do not use this:-->
<httpModules>
<add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web" />
<add name="WebSharper.Sitelets" type="WebSharper.Sitelets.HttpModule, WebSharper.Sitelets" />
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web" />
<add name="WebSharper.Sitelets" type="WebSharper.Sitelets.HttpModule, WebSharper.Sitelets" />
</modules>
<!-- This is only needed for VS Development WebServer (see above). IIS/IIS Express do not use this: -->
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
</configuration>
@o1lo01ol1o
Copy link
Author

Jquery listeners are not properly triggered when the page is loaded; in particular '$this. Select2()' fails which seems to point to either the select2 library being ubound by susbsequent imports or never being instantiated in t the first place. however, the fact that the awesomeplete code works but does not update the Var seems to suggest that the on.afterRender handlers are not being called correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment