Does anyone have suggestions for how to set the st...
# compose-web
g
Does anyone have suggestions for how to set the state (checked or not checked) of a CheckboxInput after it has been created?
On first look, you would think the checked parameter would do the trick. However, this applies the checked attribute, and according to the documentation
here
, that sets whether the checkbox is checked by default (when the page loads).
Here is a small example illustrating the problem:
Copy code
fun main() {
    renderComposable(rootElementId = "root") {
        var original by remember { mutableStateOf(false) }

        Div {
            Label(forId = "original") {
                Text("Original")
            }
            CheckboxInput(checked = original) {
                id("original")
                onInput {
                    original = it.value
                }
            }
        }

        Div {
            Label(forId = "copy") {
                Text("Copy")
            }
            CheckboxInput(checked = original) {
                id("copy")
            }
        }
    }
}
Initially, if you check the Original checkbox, the Copy checkbox follows. However if you check the Copy checkbox, it will no longer check/uncheck itself according to the value set on the checked attribute.
The above example is contrived to keep it simple, but I've run into this when implementing a master-detail view. When the master record is changed, the CheckboxInput on the form does not reflect the correct value - it retains whatever state was last activated by the user.
The value attribute, unlike other inputs, also does not affect the state.
h
Does it work in plain JS? 😄
g
I try to avoid JS at all costs. I suppose I could do it in Kotlin, just not using compose-web. According to the documentation the HTMLInputElement has a checked property that returns/sets the state. But when using compose-web, I didn't see a way to get access to the underlying HTMLInputELement that is emitted. That doesn't mean it isn't there, I just couldn't find it.
o
Hi Greg! Is there a reason why you don't want to add
Copy code
onInput {
    original = it.value
}
to the Copy checkbox? Didn't it work as well?
g
The objective is to change the checked state of a checkbox based on the value of a variable that can be changed in some way other than the checkbox itself. Here is a gist that has a more elaborate master-detail demonstration of the problem. If you click on a president on the top the "Detail" view at the bottom should update to reflect the state of the president you clicked on. Once you click on the checkbox itself, the checkbox will no longer follow the state if the selection at the top is changed. That is because the checked parameter cannot be used to set the checkbox state. Another mechanism needs to be provided to do that.
🙏 1
Here is a version of the first example like what Philip was asking about, without using compose-web (but Kotlin instead of JS) that exhibits the desired behavior. Here it has to use the checked property of the underlying HTMLInputElement to set the checked state. NOT the checked attribute of the element:
Copy code
fun HtmlCheckBoxTest(){
    var checked = false

    val checkBox1 = document.body?.appendElement("Input"){
        setAttribute("type", "checkbox")
    } as HTMLInputElement

    val checkBox2 = document.body?.appendElement("Input"){
        setAttribute("type", "checkbox")
    } as HTMLInputElement

    checkBox1.checked = checked
    checkBox2.checked = checked

    checkBox1.oninput = {
        checked = (it.target as HTMLInputElement).checked
        checkBox2.checked = checked
        true
    }
}
The variable checked is actually not even needed in this example. The point is to show how to programmatically change the checked state of the checkbox - using the checked property of the element, not the checked attribute.