Cannot set HTMLElement.style properties
I have this really simple problem I can't seem to figure out. I'm trying to use JavaScriptKit to create an element in the browsers DOM and set some CSS style on it:
import JavaScriptKit
let document = JSObject.global.document
var spanElem = document.createElement("span")
spanElem.innerText = "hello"
spanElem.style.backgroundColor = "yellow"
_ = document.body.appendChild(spanElem)
But it seems that the assignment to spanElem.style.backgroundColor doesn't have any effect. When I run this code (as main.swift), the <span> is created but its CSS style is unchanged. Reading style.backgroundColor from the browser console also shows nothing, but changing it from there works as expected:
document.getElementsByTagName('span')[0].style.backgroundColor
""
document.getElementsByTagName('span')[0].style.backgroundColor = "yellow"
"yellow"
document.getElementsByTagName('span')[0].style.backgroundColor
"yellow"
I'm using carton 0.10.0, Swift swift-wasm-5.3.1-RELEASE, JavaScriptKit 0.10.1 and am testing with newest Chrome and Safari (with same results) on macOS 10.15.7.
What am I doing wrong here?
This is a limitation of the current API design of JavaScriptKit.
spanElem.style.backgroundColor = "yellow" is evaluated as below:
var style = spanElem.style
style.backgroundColor = "yellow"
spanElem.style = style
Even style is a reference type in JavaScript world, it's expressed by value type in Swift, so spanElem.style = style re-assignment is appeared. But this assignment causes undefined behavior because HTMLElement.style is readonly property and it clears all CSS attributes.
I'll re-design JavaScriptKit API to resolve this semantics mismatch, but please use this workaround to avoid re-assignment for a while. Sorry.
import JavaScriptKit
let document = JSObject.global.document
var spanElem = document.createElement("span")
spanElem.innerText = "hello"
var style = spanElem.style as JSValue
style.backgroundColor = "yellow"
_ = document.body.appendChild(spanElem)
Thank you for your very helpful response! With it I'm no longer stuck and can continue with my project. :) One note:
I'll re-design JavaScriptKit API to resolve this semantics mismatch, but please use this workaround to avoid re-assignment for a while. Sorry.
var style = spanElem.style
I had to write spanElem.style as JSValue because I would otherwise get the following error:
[...]/main.swift:7:14: error: ambiguous use of 'subscript(dynamicMember:)'
var style = spanElem.style
This problem pops up here and there. Maybe a re-design could also alleviate this small annoyance? If there's already a document or issue use to gather such input I'd be happy to contribute this observation (and some others) there!