Closed tronical closed 1 year ago
At the heart of the issue lies that the binding for the checked property is destroyed:
CheckBox {
text: todo.title;
checked: todo.checked;
toggled => {
todo.checked = checked;
}
}
Initially the binding checked: todo.checked;
correctly fetches the data out of the model (model_data
property). But when the user clicks on the CheckBox
, the style runs this code in the TouchArea
:
touch := TouchArea {
clicked => {
if (root.enabled) {
root.checked = !root.checked;
root.toggled();
}
}
}
and the assignment to root.checked
destroys the data model binding.
We would somehow need to support two ways binding with model properties this is not easy because the runtime really expect properties so they can be merged into one property.
I've begun prototyping an approach that tries to detect two-way bindings in model data structures, synthesise a property for it and update it in the model update function.
Diagnostics wise it might be interesting to also have a pass that tries to detect cases where we know that a property has a binding and is written to somewhere else - in order to issue a warning that perhaps a two-way binding is desired.
Diagnostics wise it might be interesting to also have a pass that tries to detect cases where we know that a property has a binding and is written to somewhere else
I think we really need to be able to declare property are meant to be "readonly" or something (like the pressed
property of a TouchArea) or read-write (like the checked property of a checkbox) or meant to be set like the background
property for example.
Issue https://github.com/sixtyfpsui/sixtyfps/issues/191
For example the compiler can't know if the NativeCheckBox assignthe checked property. However we already annotate some property as being set. But it'd be better to be exlicit about it i think.
We discussed the two-way bindings separately a bit further and with regards to the model we could implement tow-way bindings for model data by using the existing callback functionality of struct PropertyTracker<ChangeHandler = ()>
in generated code to write changes back into the model.
@ogoffart I was just hit by this as well. Is there some suggested workaround for now? I can't control the checked
property of a CheckBox
from Rust anymore as soon as it was toggled once which basically makes it impossible to implement my desired UX.
Is there some suggested workaround for now?
It depends a bit of what you're doing. But we can use a workaround similar to the missing changed event https://github.com/slint-ui/slint/issues/112#issuecomment-1065866865
CheckBox {
text: {
checked = the_property; // <- Ugly workaround right there
" Check me ";
}
checked: the_property;
toggled => {
the_property = checked;
}
}
This works because the text
property is evaluated (indirectly) by the rendering engine. And it depends on the the_property
and do side effect in a binding (which is supposed to be pure, but nobody is checking).
@ogoffart I see. I worked around by using my local fork and slightly modifying CheckBox
s implementation.
I could propose this change in a PR when I have a free moment but it might be a breaking change so unsure about it.
Closing this as a duplicate of https://github.com/slint-ui/slint/issues/814
Modify the Todo example like this:
Then when running, pressing the "remove all done" button will toggle all todos. That works the first time. Then turn off a few toggles in the UI and press the "remove all done" button again.
Expected Result: All todos are checked again. Actual Result: Nothing changes in the UI.