Why is `ElementBuilderImplementation` private? How...
# compose-web
h
Why is
ElementBuilderImplementation
private? How do you implement new html elements, without copying this class?
o
There is an experimental method TagElement that takes tag: String as a parameter. What's your use case by the way?
h
I want to add a missing Html Builder function,
Canvas
and
HtmlCanvasElement
😄
o
ElementBuilderImpl is better to stay private at the moment. Maybe you can implement ElementBuilder in your code, or try the experimental method TagElement.
h
What do you mean with
TagElement
? I use
1.0.1
, so this would be the code:
Copy code
@Composable
fun Canvas(
    attrs: AttrBuilderContext<HTMLCanvasElement>? = null,
    content: ContentBuilder<HTMLCanvasElement>? = null
) {
    TagElement(
        elementBuilder = Canvas,
        applyAttrs = attrs,
        content = content
    )
}

private val Canvas: ElementBuilder<HTMLCanvasElement> = ElementBuilderImplementation("canvas") // private!
Btw, what's going to be in the content of your canvas? Will it be composable?
h
Thanks! Unfortunately, the applyAttrs function is not nullable, like every builder function https://github.com/JetBrains/compose-jb/pull/1822
Yeah, I want to include a https://chartjs.org chart
🔥 1
h
Thanks. So I want to update the chart with new data, but the chart canvas should not update compose tree
👍 1
My project has a markdown -> kt converter, and markdown can produce inline html that I wanted to handle (for example,
<span class="highlight">some text</span>
)
o
Thanks! So the problem with that experimental function is that one may want to change the element (tagName:String) value after an element is already created. And according to compose, the element should change. But we're not sure if it's valid for html elements. An html element tag can't be changed once created. An option is to delete an old element and create a new one. ideally one would never change the tag name, but it seems we can't restrict it. That's why it's still experimental.
d
Huh interesting. For sure I never need to change a tag in my project.
I guess I'm still missing how people can edit the tag name. Using a ref from a side effect?
o
By calling the same TagElement with different argument: var tagName by remember {mutableStateOf("div")} TagElement(tagName)
d
Wouldn't that just remove the old tag and put it a new one when the page recomposes?
o
It's an option. But it doesn't work like this for now.
d
OK I didn't realize it was so nuanced 🙂 Good luck with the API! If it helps, I'd just expect it to re-compose a page with a new tag element -- basically whatever this would do:
Copy code
@Composable
fun DivOrSpan(useDiv: Boolean, @Composable content: () -> Unit) {
   if (useDiv) Div { content() } else Span { content() }
}

@Composable
fun SomeWidget() {
  var useDiv by { mutableStateOf(true) }
  DivOrSpan(useDiv) {
     Text("Hello")
  }
  Button(onClick = { useDiv = !useDiv })
}
👍 1
h
This was more difficult than expected, because chart.js was difficult to integrate with Kotlin JS. Compose was easy 😄
o
What did cause trouble?
h
Chart.js's interesting "typed" definitions
r
Side question re the "don't want users to change tags" thingy: that sounds a lot like a novel use case for the `const`/`constexpr` modifier I've seen on YouTrack. Would it fit, do you think? In particular making the
tag
parameter
const
o
@rnett do you mean something like:
Copy code
@Composable
fun TagName(const tagName: String, ...)
so only a const value can be used as an argument for tagName? i think it might help. at the same time, it seems to be a really rare use case. to be honest I've never had such a need before 🙂 (unlike cases described in KT-14652)
r
Yeah, that's what I was wondering
p
Hi @hfhbd how did you manage to integrate chartjs in the end?
h
@paoloconte See https://github.com/hfhbd/chartJS-compose. nothing special regarding compose
👏 1