Closed JordanMarr closed 2 years ago
you can access them in the standard way by using .children
[<LitElement("my-element">]
let MyElement() =
let host, _ = LitElement.init(cfg -> cfg.useShadowDom <- false)
host.children //
html $""" ... content ... """
// for shadow dom you need to use shadowRoot
[<LitElement("my-shadow-element">]
let MyElement() =
let host, _ = LitElement.init()
host.shadowRoot.children // children are inside the shadow DOM
html $""" ... content ... """
Is there any particular case you have in mind?
I know is more of a discussion than an issue
it would be nice indeed if the discussions were enabled in this repo
oh looks like the types don't have the children
property but in the browser works
Yes, the discussion forum feature would be great in this repo!
So I was just messing around to see what kind of stuff I can automate with custom elements.
I wanted to recreate the FluentUI React Stack
control that lets you pass in an array of ReactElement
's and it will do some grid stuff to it.
I ended up doing it with a HookComponent
:
[<HookComponent>]
let HorizontalStack(children: (int * TemplateResult) list) =
let columns =
children
|> List.map (fun (colSize, child) ->
html $"""
<div class="ms-Grid-col ms-md{colSize}">
{child}
</div>
"""
)
html $"""
<div class="ms-Grid" dir="ltr">
<div class="ms-Grid-row">
{columns |> Lit.ofList}
</div>
</div>
"""
Usage:
Ctrls.HorizontalStack [
3, html $"""
<fluent-icon icon-name="Car"></fluent-icon>
"""
9, html $"""
<div>
<fluent-button @click={Ev(fun _ -> dispatch ForgePrev)} appearance="accent">Back</fluent-button>
<div style="display: inline-block; vertical-align: -webkit-baseline-middle">{model.ForgePageIdx + 1}</div>
<fluent-button @click={Ev(fun _ -> dispatch ForgeNext)} appearance="accent">Next</fluent-button>
</div>
<fluent-data-grid style="max-height: 30em; overflow-y: auto;" .rowsData={model.ForgeProjects}>
</fluent-data-grid>
"""
]
However, I really want to have something more like this:
<fluent-stack horizontal gap="10px" sizes="3,9">
<div>Col A</div>
<div>Col B</div>
</fluent-stack>
This is very tricky to do with CustomElements, the most straight approach would be to use Shadow DOM + Slots since that's the primary use case for it
[<LitElement("shadow-card">]
let MyElement() =
LitElement.init() |> ignore
html
$"""
<article class="card">
<!-- Any other structures, styles and logic -->
<header class="card-header">
<slot name=header></slot>
</header>
<slot></slot>
</article>
"""
with slots in this case we can do content projection for the header content and the rest of the elements, you would use it just like you want it
<shadow-card>
<!-- Both of these go inside the header slot,
they don't overwrite each other -->
<h1 slot="header">Title</h1>
<p slot="header">Sub title</p>
<!-- the rest go to the unnamed slot -->
<section>The rest of the content</section>
<aside>Any other content </aside>
</shadow-card>
but as you may be aware, that requires a little bit more of planning in regards how to consume external styles or define your own for that component
Welp... tricky is right. There are so many rules and quirks that it makes hook components look a lot more attractive.
I enabled the discussions for the repo :)
Yes, besides the templates and other Lit concepts, as @AngelMunoz said, you do thinks the "web components way" which in this case it's probably slots.
The idea of adding the HookComponent
was to have the benefit of Lit templating with the advantages of F# function composition, so passing the children as an argument looks right to me :)
I know is more of a discussion than an issue, but for lack of a discussion forum I will post it here: Is it possible to access an array of children elements in my custom element?