Skip to content

Commit b4fd6e0

Browse files
committed
Add validation section to READEME
1 parent 0810a84 commit b4fd6e0

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ BindProperty("%SpinBox", nameof(SpinBox.Value), nameof(SpinBoxValue), BindingMod
102102

103103
</details>
104104

105+
<br/>
106+
105107
### Deep property binding
106108
Bind to property members on other objects. These objects and properties must be relative to the current scene script.
107109

@@ -128,6 +130,7 @@ public PlayerData SelectedPlayerData
128130
```
129131
</details>
130132

133+
<br/>
131134

132135
### Formatters
133136
A binding can be declared with an optional formatter to format the value between your control and the target property or implement custom type conversion. Formatters can also be used to modify list items properties by returning a `ListItem` object.
@@ -156,6 +159,8 @@ This formatter will set a string value into the target control using the input v
156159

157160
</details>
158161

162+
<br/>
163+
159164
### List Binding
160165
List bindings can be bound to an `ObservableList<T>` to benefit from adding and removing items
161166

@@ -195,6 +200,8 @@ public class PlayerDataListFormatter : IValueFormatter
195200

196201
</details>
197202

203+
<br/>
204+
198205
### Scene List Binding
199206
Bind an `ObservableList<T>` to a control's child list to add/remove children. The target scene must have a script attached and inherit from `ObservableNode`. It must also provide an implementation for `SetViewModeldata()`
200207

@@ -226,3 +233,80 @@ public partial class PlayerDataListItem : ObservableNode
226233
}
227234
```
228235
</details>
236+
237+
<br/>
238+
239+
### Control input validation
240+
Control bindings can be validated by either:
241+
* Adding validation function to the binding
242+
* Throwing a `ValidationException` from a formatter
243+
244+
There also two main ways of subscribing to validation changed events:
245+
* Subscribe to the `ControlValidationChanged` event on the `ObservableNode` your bindings reside on
246+
* Add a validation handler to the control binding
247+
248+
You can also use the `HasErrors` property on an `ObservableNode` to notify your UI of errors and review a full list of validation errors using the `GetValidationMessages()` method.
249+
250+
251+
<details>
252+
<summary>details</summary>
253+
<br/>
254+
255+
**Adding validators and validation callbacks**
256+
257+
Property bindings implement a fluent builder pattern for modify the binding upon creation to add validators and a validator callback.
258+
259+
You can have any number of validators but only one validation callback.
260+
261+
Validators are run the in the order they are registered and validation will stop at the first validator to return a non-empty string. Validators are run before formatters. The formatter will not be executed if a validation error occurs.
262+
263+
This example adds two validators and a callback to modulate the control and set the tooltip text.
264+
265+
```c#
266+
BindProperty("%LineEdit", nameof(LineEdit.Text), $"{nameof(SelectedPlayerData)}.{nameof(PlayerData.Health)}", BindingMode.TwoWay)
267+
.AddValidator(v => int.TryParse((string)v, out int value) ? null : "Health must be a number")
268+
.AddValidator(v => int.TryParse((string)v, out int value) && value > 0 ? null : "Health must be greater than 0")
269+
.AddValidationHandler((control, isValid, message) => {
270+
control.Modulate = isValid ? Colors.White : Colors.Red;
271+
control.TooltipText = message;
272+
});
273+
```
274+
275+
**Subscribing to `ControlValidationChanged` events**
276+
277+
If you want to have common behaviour for many or all controls, you can subscribe to the `ControlValidationChanged` event and get updates about all control validations.
278+
279+
This example subscribes to all validation changed events to modulate the target control and set the tooltip text.
280+
281+
The last validation error message is also stored in the local ErrorMessage property to be bound to a UI label.
282+
283+
```csharp
284+
public partial class MyClass : ObservableNode
285+
{
286+
private string errorMessage;
287+
public string ErrorMessage
288+
{
289+
get { return errorMessage; }
290+
set { SetValue(ref errorMessage, value); }
291+
}
292+
293+
public override void _Ready()
294+
{
295+
BindProperty("%ErrorLabel", nameof(Label.Visible), nameof(HasErrors), BindingMode.OneWay);
296+
BindProperty("%ErrorLabel", nameof(Label.Text), nameof(ErrorMessage), BindingMode.OneWay);
297+
ControlValidationChanged += OnControlValidationChanged;
298+
}
299+
300+
private void OnControlValidationChanged(control, propertyName, message, isValid)
301+
{
302+
control.Modulate = isValid ? Colors.White : Colors.Red;
303+
control.TooltipText = message;
304+
305+
// set properties to bind to
306+
ErrorMessage = message;
307+
ValidationSummary = GetValidationMessages();
308+
};
309+
}
310+
```
311+
312+
</details>

0 commit comments

Comments
 (0)