using Connected.Annotations;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class Form : UIComponent, IDisposable, IForm
{
protected string Classname =>
new CssBuilder("mud-form")
.AddClass(Class)
.Build();
///
/// Child content of component.
///
[Parameter]
[Category(CategoryTypes.Form.ValidatedData)]
public RenderFragment ChildContent { get; set; }
///
/// Validation status. True if the form is valid and without errors. This parameter is two-way bindable.
///
[Parameter]
[Category(CategoryTypes.Form.ValidationResult)]
public bool IsValid
{
get => _valid && ChildForms.All(x => x.IsValid);
set
{
_valid = value;
}
}
// Note: w/o any children the form is automatically valid.
// It stays valid, as long as non-required fields are added or
// a required field is added or the user touches a field that fails validation.
private bool _valid = true;
private void SetIsValid(bool value)
{
if (IsValid == value)
return;
IsValid = value;
IsValidChanged.InvokeAsync(IsValid).AndForget();
}
// Note: w/o any children the form is automatically valid.
// It stays valid, as long as non-required fields are added or
// a required field is added or the user touches a field that fails validation.
///
/// True if any field of the field was touched. This parameter is readonly.
///
[Parameter]
[Category(CategoryTypes.Form.Behavior)]
public bool IsTouched { get => _touched; set {/* readonly parameter! */ } }
private bool _touched = false;
///
/// Validation debounce delay in milliseconds. This can help improve rendering performance of forms with real-time validation of inputs
/// i.e. when textfields have Immediate="true".
///
[Parameter]
[Category(CategoryTypes.Form.Behavior)]
public int ValidationDelay { get; set; } = 300;
///
/// When true, the form will not re-render its child contents on validation updates (i.e. when IsValid changes).
/// This is an optimization which can be necessary especially for larger forms on older devices.
///
[Parameter]
[Category(CategoryTypes.Form.Behavior)]
public bool SuppressRenderingOnValidation { get; set; } = false;
///
/// When true, will not cause a page refresh on Enter if any input has focus.
///
///
/// https://www.w3.org/TR/2018/SPSD-html5-20180327/forms.html#implicit-submission
/// Usually this is not wanted, as it can cause a page refresh in the middle of editing a form.
/// When the form is in a dialog this will cause the dialog to close. So by default we suppress it.
///
[Parameter]
[Category(CategoryTypes.Form.Behavior)]
public bool SuppressImplicitSubmission { get; set; } = true;
///
/// Raised when IsValid changes.
///
[Parameter] public EventCallback IsValidChanged { get; set; }
///
/// Raised when IsTouched changes.
///
[Parameter] public EventCallback IsTouchedChanged { get; set; }
///
/// Raised when a contained IFormComponent changes its value
///
[Parameter] public EventCallback FieldChanged { get; set; }
// keeps track of validation. if the input was validated at least once the value will be true
protected HashSet _formControls = new();
protected HashSet _errors = new();
///
/// A default validation func or a validation attribute to use for form controls that don't have one.
/// Supported types are:
/// Func<T, bool> ... will output the standard error message "Invalid" if false
/// Func<T, string> ... outputs the result as error message, no error if null
/// Func<T, IEnumerable< string >> ... outputs all the returned error messages, no error if empty
/// Func<object, string, IEnumerable< string >> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty
/// Func<T, Task< bool >> ... will output the standard error message "Invalid" if false
/// Func<T, Task< string >> ... outputs the result as error message, no error if null
/// Func<T, Task<IEnumerable< string >>> ... outputs all the returned error messages, no error if empty
/// Func<object, string, Task<IEnumerable< string >>> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty
/// System.ComponentModel.DataAnnotations.ValidationAttribute instances
///
[Parameter]
[Category(CategoryTypes.FormComponent.Validation)]
public object Validation { get; set; }
///
/// If a field already has a validation, override it with .
///
[Parameter]
[Category(CategoryTypes.FormComponent.Validation)]
public bool? OverrideFieldValidation { get; set; }
///
/// Validation error messages.
///
[Parameter]
[Category(CategoryTypes.Form.ValidationResult)]
public string[] Errors
{
get => _errors.ToArray();
set { /* readonly */ }
}
[Parameter] public EventCallback ErrorsChanged { get; set; }
///
/// Specifies the top-level model object for the form. Used with Fluent Validation
///
#nullable enable
[Parameter]
[Category(CategoryTypes.Form.ValidatedData)]
public object? Model { get; set; }
#nullable disable
private HashSet