Closed evilz closed 2 years ago
I can confirm that Lit supports this by default in this sample repl
but can you share a more complete example of what you were trying to do? a simple component definition perhaps
Yes here a port of the tuturial of Lit.dev
module Lit.TodoMVC.App
open Lit
open Browser.Types
open Browser
open Fable.Core.JsInterop
type ToDoItem =
{ Text: string
mutable Completed: bool }
let styles =
[ css
$"""
.completed {{
text-decoration-line: line-through;
color: #777;
}}""" ]
[<LitElement("todo-list")>]
let ToDoList () =
// This call is obligatory to initialize the web component
let host, props =
LitElement.init
(fun init ->
init.styles <- styles
init.useShadowDom
init.props <-
{| listItems =
Prop.Of(
[ { Text = "Start Lit tutorial"
Completed = true }
{ Text = "Make to-do list"
Completed = false } ]
)
hideCompleted = Prop.Of(false) |})
let input () : HTMLInputElement =
host?renderRoot?querySelector ("#newitem")
let addToDo (event: Event) =
//let input = event.target
//props.firstname.Value <- input.Value
let input = input ()
props.listItems.Value <-
{ Text = input.Value
Completed = false }
:: props.listItems.Value
input.value <- ""
host.requestUpdate ()
let toggleCompleted (item: ToDoItem) =
item.Completed <- not item.Completed
host.requestUpdate ()
let getItemTemplate item =
html
$"""<li class={if item.Completed then
"completed"
else
""}
@click={fun _ -> toggleCompleted (item)}>{item.Text}</li>"""
let setHideCompleted (e: Event) =
props.hideCompleted.Value <- (e.target :?> HTMLInputElement).``checked``
let items =
if props.hideCompleted.Value then
props.listItems.Value
|> List.filter (fun item -> not item.Completed)
else
props.listItems.Value
let caughtUpMessage =
html
$"""
<p>
You're all caught up!
</p>
"""
let todos =
html
$"""<ul>
{items
|> Lit.mapUnique (fun item -> item.Text) getItemTemplate}
<!-- TODO: Render list items. -->
</ul>
"""
let todosOrMessage =
if items.Length > 0 then
todos
else
caughtUpMessage
html
$"""
<h2>To Do</h2>
{todosOrMessage}
<input id="newitem" aria-label="New item">
<button @click={addToDo}>Add</button>
<br>
<label>
<input type="checkbox"
@change={setHideCompleted}
?checked={props.hideCompleted}>
Hide completed
</label>
"""
<!doctype html>
<html lang="en">
<head>
<title>Lit.TodoMVC</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="fable.ico" />
<!-- Used to hide custom components until they are defined and prevent a flash of unstyled content -->
<style>
*:not(:defined) { display:none }
</style>
<style>
body {
font-family: 'Open Sans', sans-serif;
font-size: 1.5em;
padding-left: 0.5em;
}
</style>
</head>
<body>
<script type="module" src="./build/client/App.js"></script>
<todo-list />
</body>
</html>
Thanks for pointing this @evilz! You're definitely right. I was using .el
as a "fake" property to access the HTMLElement because it was not easy to make LitElement inherit from it (right now, HTMLElement is defined as a interface in Fable.Browser.Dom), but renderRoot
is a much better choice because it matches Lit documentation and it also gives you directly the shadowRoot when present. I've changed it :+1:
Hello,
I think we should had
renderRoot
in typeLitElement
.I try to do something like this
Maybe I miss something with
host.el
??? when I changeuseShadowDom
to false this is working.What do you think ?