// 05-form/form.qml // Form: GridLayout with labels, inputs, owned state, and validation. // Pure QML. Run with: qml6 form.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts ApplicationWindow { id: root width: 420; height: 360 visible: true title: "QML 05: Form" property string name: "" property string email: "" property int age: 0 property string password: "" property string confirmPassword: "" readonly property bool passwordsMatch: password === confirmPassword readonly property bool isValid: name.length > 0 && email.includes("@") && age >= 13 && passwordsMatch && password.length >= 8 GridLayout { anchors.fill: parent anchors.margins: 16 columnSpacing: 12 rowSpacing: 8 columns: 2 Label { text: "Name:"; Layout.alignment: Qt.AlignRight } TextField { id: nameField Layout.fillWidth: true focus: true text: root.name placeholderText: "Your name" Accessible.name: "Name" onTextEdited: root.name = text } Label { text: "Email:"; Layout.alignment: Qt.AlignRight } TextField { id: emailField Layout.fillWidth: true text: root.email placeholderText: "you@example.com" Accessible.name: "Email" onTextEdited: root.email = text } Label { text: "Age:"; Layout.alignment: Qt.AlignRight } SpinBox { from: 0; to: 120 value: root.age Accessible.name: "Age" onValueModified: root.age = value } Label { text: "Password:"; Layout.alignment: Qt.AlignRight } TextField { id: pwField Layout.fillWidth: true text: root.password echoMode: TextInput.Password Accessible.name: "Password" onTextEdited: root.password = text } Label { text: "Confirm:"; Layout.alignment: Qt.AlignRight } TextField { id: confirmField Layout.fillWidth: true text: root.confirmPassword echoMode: TextInput.Password Accessible.name: "Confirm password" onTextEdited: root.confirmPassword = text } Item { Layout.columnSpan: 2; Layout.fillWidth: true; implicitHeight: 12 } // spacer Label { text: ""; Layout.alignment: Qt.AlignRight } // empty cell RowLayout { Layout.fillWidth: true spacing: 12 Text { text: root.isValid ? "✓ Valid" : "✗ " + (root.passwordsMatch ? "" : "passwords don't match") color: root.isValid ? "green" : (root.passwordsMatch ? "#888" : "red") Layout.fillWidth: true } Button { text: "Submit" enabled: root.isValid onClicked: console.log("submitted:", JSON.stringify({ name: root.name, email: root.email, age: root.age, passwordLength: root.password.length })) } } } }