Repository: slint-ui/slint

Issue #814: Allow two-way binding to struct members
Created: 2022-01-07T10:51:07Z
It is currently only possible to bind a current-value or checked attribute of a widget to a property. This requires creating single properties for each control in order to process their value in the host application or to create a struct and manually fill the values in a .60 callback.
It would be convenient to be able to map attributes to members of a struct property, like:
struct Settings {
    value_1: bool,
    value_2: bool
}

Window {
    property <Setttings> settings;

    Checkbox {
        text: "Value 1";
        checked <=> settings.value_1;
    }
    Checkbox {
        text: "Value 2";
        checked <=> settings.value_2;
    }

}

Duplicate issue #2013: Two-way bindings to item in a model
Created: 2022-12-21T19:29:51Z
Maybe this is fixed in the updated syntax, but with the current version of 0.3.3 (using rust) issues exist in how/where properties are declared that determine if two-way bindings are possible in .slint files.
Regular properties work with two-way bindings as expected:
export Sample1 := Rectangle {
    in-out property <string> myprop1;
    in-out property <int> myprop2;
    LineEdit { text <=> myprop1; }
    SpinBox { value <=> myprop2; }
}

But if a struct is used things break:
export struct MyStruct := {
    string_prop: string,
    int_prop: int,
}

export Sample2 := Rectangle {
    in-out property <MyStruct> myprops;
    LineEdit { text <=> myprops.string_prop; } // gives: The expression in a two way binding must be a property reference
    LineEdit { text: myprops.string_prop; } // One-way bindings work
}

There is a workaround for the struct problem using inheritance though (not sure if slint is intended to be used like this):
export FakeStruct := Rectangle {
    in-out property <string> string_prop;
    in-out propert <int> int_prop;
}

export Sample2a := FakeStruct {
    LineEdit { text <=> string_prop; } // now that string_prop is inherited it works
}

Also the use of arrays (at least in for loops) may break things:
// This one works
export Sample3 := Rectangle {
    in-out property <[string]> multiprop;
    in-out property <[length]> widths;
    for my_prop[idx] in multiprop : HorizontalLayout {
        width: widths[idx];
        Text { text: my_prop; }
    }
}

// But this doesn't
export Sample3 := Rectangle {
    in-out property <[string]> multiprop;
    in-out property <[length]> widths;
    for my_prop[idx] in multiprop : HorizontalLayout {
        width: widths[idx];
        Text { text <=> my_prop; } // gives: The expression in a two way binding must be a property reference
    }
}

// And neither does this
export Sample3 := Rectangle {
    in-out property <[string]> multiprop;
    in-out property <[length]> widths;
    in-out property <string> sometext;
    for my_prop[idx] in multiprop : HorizontalLayout {
        width <=> widths[idx]; // gives: The expression in a two way binding must be a property reference
        Text { text <=> sometext; } // now works with non-array property
    }
}

Would the above examples be expected to work? Feel free to point out any incorrect assumptions on my part or any part of the documentation that mentions or explains the observed behaviour that I might have missed.

Closing comment (2022-12-22T07:57:24Z): Thank you for your detailed and informative report.
You're encountering three separate issues related to binding:

binding to member of struct, (#814)
binding to the model data,
and binding to a particular element of a model using the [] syntax.

We are aware of these issues and would like to see them supported in the future. However, at this time they are not yet implemented.
We have ongoing discussions about the struct binding issue in #814
For the two other issue we could use a similar approach to the struct binding issue and call model.set_row_data behind the scenes when the property is changed. However, implementing any of these issues is not a trivial task.
I am rewording the title of this issue to keep track of the binding to model issue, while the binding to struct is tracked in #814