diff --git a/src/FormBuilder/Components/FieldPropertyEditor.razor b/src/FormBuilder/Components/FieldPropertyEditor.razor
index bc4aa2b..aea7082 100644
--- a/src/FormBuilder/Components/FieldPropertyEditor.razor
+++ b/src/FormBuilder/Components/FieldPropertyEditor.razor
@@ -33,20 +33,13 @@
- @if (Field is TextField textField)
- {
-
-
-
- }
-
@if (Field is NumericField numericIntField)
{
-
+
}
@if (Field is NumericField numericDecimalField)
{
-
+
}
@if (Field is DateField dateField)
@@ -83,7 +76,7 @@
}
}
-
-
+
+
}
diff --git a/src/FormBuilder/Components/FieldValidatorsEditor.razor b/src/FormBuilder/Components/FieldValidatorsEditor.razor
new file mode 100644
index 0000000..7374997
--- /dev/null
+++ b/src/FormBuilder/Components/FieldValidatorsEditor.razor
@@ -0,0 +1,60 @@
+@using FormBuilder.Models
+
+
+
+
+ @switch (Field.Type)
+ {
+ case FieldType.Text:
+
+
+ break;
+ case FieldType.NumericInt or FieldType.NumericDecimal:
+
+ break;
+ }
+
+
+
+
+
+ @foreach (var validator in Field.Validators)
+ {
+ @switch (validator)
+ {
+ case RequiredValidator requiredValidator:
+
+
+
+ break;
+ case EmailValidator emailValidator:
+
+
+
+ break;
+ case LengthValidator lengthValidator:
+
+
+
+ break;
+ case NumericRangeValidator numericRangeValidator:
+
+
+
+ break;
+ }
+ }
+
+
diff --git a/src/FormBuilder/Components/FieldValidatorsEditor.razor.cs b/src/FormBuilder/Components/FieldValidatorsEditor.razor.cs
new file mode 100644
index 0000000..3d5bfdc
--- /dev/null
+++ b/src/FormBuilder/Components/FieldValidatorsEditor.razor.cs
@@ -0,0 +1,29 @@
+using FormBuilder.Factories;
+using FormBuilder.Models;
+using Microsoft.AspNetCore.Components;
+
+namespace FormBuilder.Components;
+
+public partial class FieldValidatorsEditor : ComponentBase
+{
+ #region Parameters
+
+ [Parameter, EditorRequired]
+ public Field Field { get; set; } = default!;
+
+ [Parameter]
+ public EventCallback FieldChanged { get; set; }
+
+ #endregion
+
+ private void RaiseFieldChanged()
+ {
+ FieldChanged.InvokeAsync(Field);
+ }
+
+ private void AddValidator(ValidatorType validatorType)
+ {
+ Field.Validators.Add(ValidatorFactory.Create(validatorType));
+ FieldChanged.InvokeAsync(Field);
+ }
+}
diff --git a/src/FormBuilder/Components/FormEditor.razor b/src/FormBuilder/Components/FormEditor.razor
index 8708313..d8e4f30 100644
--- a/src/FormBuilder/Components/FormEditor.razor
+++ b/src/FormBuilder/Components/FormEditor.razor
@@ -1,7 +1,7 @@
@using FormBuilder.Models
-
+
@if (_formDefinition.Id is not null)
{
@@ -47,10 +47,10 @@
-
+
-
+
@@ -79,12 +79,13 @@
}
- @if (_formDefinition.Fields.Count > 0)
- {
-
- }
-
-
+
+ @if (_formDefinition.Fields.Count > 0)
+ {
+
+ }
+
+
diff --git a/src/FormBuilder/Components/FormEditor.razor.cs b/src/FormBuilder/Components/FormEditor.razor.cs
index 44cf00d..532803c 100644
--- a/src/FormBuilder/Components/FormEditor.razor.cs
+++ b/src/FormBuilder/Components/FormEditor.razor.cs
@@ -74,7 +74,7 @@ private async Task UpdateFormDesignJsonAsync()
private Task AddField(FieldType fieldType)
{
- var field = FieldFactory.CreateField(fieldType);
+ var field = FieldFactory.Create(fieldType);
field.Label = fieldType.ToString();
_formDefinition.Fields.Add(field);
SelectedField = field;
@@ -106,7 +106,7 @@ private Task HandleFieldPropertyChanged(FieldPropertyChangedArgs args)
///
private void ChangeFieldType(FieldType newType, Field oldField)
{
- var newField = FieldFactory.CreateFieldFrom(newType, oldField);
+ var newField = FieldFactory.CreateFrom(newType, oldField);
var index = _formDefinition.Fields.IndexOf(oldField);
_formDefinition.Fields[index] = newField; // Replace the old field with the new one, old one will be deleted by GC
SelectedField = newField;
diff --git a/src/FormBuilder/Components/FormField.razor b/src/FormBuilder/Components/FormField.razor
index 09968d1..604e807 100644
--- a/src/FormBuilder/Components/FormField.razor
+++ b/src/FormBuilder/Components/FormField.razor
@@ -10,7 +10,7 @@
Name="@textField.Name"
@bind-Value="textField.Value"
Placeholder="@textField.Placeholder"
- MaxLength="@textField.MaxLength"
+ MaxLength="@textField.GetMaxLength()"
ReadOnly="Disabled">
break;
@@ -28,8 +28,8 @@
Name="@numericIntField.Name"
@bind-Value="numericIntField.Value"
Placeholder="@numericIntField.Placeholder"
- Min="numericIntField.Min"
- Max="numericIntField.Max"
+ Min="numericIntField.GetMin()"
+ Max="numericIntField.GetMax()"
ShowUpDown="numericIntField.ShowUpDown"
Step="@numericIntField.Step"
Format="@numericIntField.Format"
@@ -41,8 +41,8 @@
Name="@numericField.Name"
@bind-Value="numericField.Value"
Placeholder="@numericField.Placeholder"
- Min="numericField.Min"
- Max="numericField.Max"
+ Min="numericField.GetMin()"
+ Max="numericField.GetMax()"
ShowUpDown="numericField.ShowUpDown"
Step="@numericField.Step"
Format="@numericField.Format"
@@ -100,7 +100,7 @@
Text="@lengthValidator.Text">
break;
- case RangeValidator rangeValidator:
+ case NumericRangeValidator rangeValidator:
-
-
-
-
-
diff --git a/src/FormBuilder/Components/NumericFieldPropertyEditor.razor.cs b/src/FormBuilder/Components/NumericFieldEditor.razor.cs
similarity index 66%
rename from src/FormBuilder/Components/NumericFieldPropertyEditor.razor.cs
rename to src/FormBuilder/Components/NumericFieldEditor.razor.cs
index 4a2afb8..e62b83c 100644
--- a/src/FormBuilder/Components/NumericFieldPropertyEditor.razor.cs
+++ b/src/FormBuilder/Components/NumericFieldEditor.razor.cs
@@ -3,7 +3,7 @@
namespace FormBuilder.Components;
-public partial class NumericFieldPropertyEditor : ComponentBase where TValue : struct
+public partial class NumericFieldEditor : ComponentBase where TValue : struct
{
[Parameter, EditorRequired]
public NumericField Field { get; set; } = default!;
@@ -11,18 +11,6 @@ public partial class NumericFieldPropertyEditor : ComponentBase where TV
[Parameter]
public EventCallback> FieldChanged { get; set; }
- private void OnMinChanged(decimal? value)
- {
- Field.Min = value;
- FieldChanged.InvokeAsync(Field);
- }
-
- private void OnMaxChanged(decimal? value)
- {
- Field.Max = value;
- FieldChanged.InvokeAsync(Field);
- }
-
private void OnStepChanged(string value)
{
Field.Step = value;
diff --git a/src/FormBuilder/Components/ValidatorPropertyEditor.razor b/src/FormBuilder/Components/ValidatorPropertyEditor.razor
new file mode 100644
index 0000000..a9e8bdd
--- /dev/null
+++ b/src/FormBuilder/Components/ValidatorPropertyEditor.razor
@@ -0,0 +1,42 @@
+@using FormBuilder.Models
+@typeparam TValue where TValue : FormBuilder.Models.Validator
+
+
+
+
+
+
+
+
+
+
+ @switch (Validator)
+ {
+ case RequiredValidator requiredValidator:
+
+
+
+
+
+
+
+
+ break;
+ case LengthValidator lengthValidator:
+
+
+
+
+
+
+ break;
+ case NumericRangeValidator numericRangeValidator:
+
+
+
+
+
+
+ break;
+ }
+
diff --git a/src/FormBuilder/Components/ValidatorPropertyEditor.razor.cs b/src/FormBuilder/Components/ValidatorPropertyEditor.razor.cs
new file mode 100644
index 0000000..39f294d
--- /dev/null
+++ b/src/FormBuilder/Components/ValidatorPropertyEditor.razor.cs
@@ -0,0 +1,74 @@
+using FormBuilder.Models;
+using Microsoft.AspNetCore.Components;
+
+namespace FormBuilder.Components;
+
+public partial class ValidatorPropertyEditor : ComponentBase where TValue : Validator
+{
+ #region Parameters
+
+ [Parameter, EditorRequired]
+ public TValue Validator { get; set; } = default!;
+
+ [Parameter]
+ public EventCallback ValidatorChanged { get; set; }
+
+ #endregion
+
+ private void OnTextChanged(string value)
+ {
+ Validator.Text = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+
+ private void OnShowAsPopupChanged(bool value)
+ {
+ Validator.ShowAsPopup = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+
+ private void OnShowRequiredHintChanged(bool value)
+ {
+ if (Validator is RequiredValidator requiredValidator)
+ {
+ requiredValidator.ShowRequiredHint = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+ }
+
+ private void OnMinLengthChanged(int? value)
+ {
+ if (Validator is LengthValidator lengthValidator)
+ {
+ lengthValidator.MinLength = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+ }
+
+ private void OnMaxLengthChanged(int? value)
+ {
+ if (Validator is LengthValidator lengthValidator)
+ {
+ lengthValidator.MaxLength = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+ }
+
+ private void OnMinChanged(int value)
+ {
+ if (Validator is NumericRangeValidator numericRangeValidator)
+ {
+ numericRangeValidator.Min = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+ }
+
+ private void OnMaxChanged(int value)
+ {
+ if (Validator is NumericRangeValidator numericRangeValidator)
+ {
+ numericRangeValidator.Max = value;
+ ValidatorChanged.InvokeAsync(Validator);
+ }
+ }
+}
diff --git a/src/FormBuilder/Converters/ValidatorJsonConverter.cs b/src/FormBuilder/Converters/ValidatorJsonConverter.cs
index 9638655..79c776e 100644
--- a/src/FormBuilder/Converters/ValidatorJsonConverter.cs
+++ b/src/FormBuilder/Converters/ValidatorJsonConverter.cs
@@ -28,7 +28,7 @@ public override Validator Read(ref Utf8JsonReader reader, Type typeToConvert, Js
ValidatorType.Required => JsonSerializer.Deserialize(rootElement.GetRawText(), options),
ValidatorType.Length => JsonSerializer.Deserialize(rootElement.GetRawText(), options),
ValidatorType.Email => JsonSerializer.Deserialize(rootElement.GetRawText(), options),
- ValidatorType.Range => JsonSerializer.Deserialize(rootElement.GetRawText(), options),
+ ValidatorType.NumericRange => JsonSerializer.Deserialize(rootElement.GetRawText(), options),
_ => throw new NotSupportedException($"The value of the validator type '{enumValidatorType}' is not supported"),
};
diff --git a/src/FormBuilder/Factories/FieldFactory.cs b/src/FormBuilder/Factories/FieldFactory.cs
index c88a3c9..1a83b68 100644
--- a/src/FormBuilder/Factories/FieldFactory.cs
+++ b/src/FormBuilder/Factories/FieldFactory.cs
@@ -9,13 +9,13 @@ public static class FieldFactory
{
///
/// Creates a new field model based on the provided fieldType.
- /// List of available field types: TextField, NumericIntField, NumericDoubleField, SelectField, DateField.
+ /// List of available field types: TextField, NumericIntField, NumericDecimalField, SelectField, DateField.
///
/// The type of the field to create.
///
/// A generic instance of the field based on the provided fieldType.
///
- public static Field CreateField(FieldType fieldType)
+ public static Field Create(FieldType fieldType)
{
return fieldType switch
{
@@ -36,9 +36,9 @@ public static Field CreateField(FieldType fieldType)
///
/// A generic instance of the field based on the provided fieldType.
///
- public static Field CreateFieldFrom(FieldType newFieldType, Field oldField)
+ public static Field CreateFrom(FieldType newFieldType, Field oldField)
{
- var newField = CreateField(newFieldType);
+ var newField = Create(newFieldType);
newField.Label = oldField.Label;
newField.Placeholder = oldField.Placeholder;
newField.ReadOnly = oldField.ReadOnly;
diff --git a/src/FormBuilder/Factories/ValidatorFactory.cs b/src/FormBuilder/Factories/ValidatorFactory.cs
new file mode 100644
index 0000000..491ae5a
--- /dev/null
+++ b/src/FormBuilder/Factories/ValidatorFactory.cs
@@ -0,0 +1,33 @@
+using FormBuilder.Models;
+
+namespace FormBuilder.Factories;
+
+///
+/// Factory class for creating validators.
+///
+public static class ValidatorFactory
+{
+ ///
+ /// Creates a validator based on the given type.
+ ///
+ ///
+ /// The type of the validator to create.
+ ///
+ ///
+ /// A new instance of the validator based on the provided type.
+ ///
+ ///
+ /// Thrown when the provided validator type is not recognized.
+ ///
+ public static Validator Create(ValidatorType validatorType)
+ {
+ return validatorType switch
+ {
+ ValidatorType.Required => new RequiredValidator(),
+ ValidatorType.Length => new LengthValidator(),
+ ValidatorType.Email => new EmailValidator(),
+ ValidatorType.NumericRange => new NumericRangeValidator(),
+ _ => throw new ArgumentOutOfRangeException(nameof(validatorType), validatorType, null)
+ };
+ }
+}
diff --git a/src/FormBuilder/Models/DateField.cs b/src/FormBuilder/Models/Fields/DateField.cs
similarity index 100%
rename from src/FormBuilder/Models/DateField.cs
rename to src/FormBuilder/Models/Fields/DateField.cs
diff --git a/src/FormBuilder/Models/Field.cs b/src/FormBuilder/Models/Fields/Field.cs
similarity index 100%
rename from src/FormBuilder/Models/Field.cs
rename to src/FormBuilder/Models/Fields/Field.cs
diff --git a/src/FormBuilder/Models/FieldType.cs b/src/FormBuilder/Models/Fields/FieldType.cs
similarity index 100%
rename from src/FormBuilder/Models/FieldType.cs
rename to src/FormBuilder/Models/Fields/FieldType.cs
diff --git a/src/FormBuilder/Models/NumericField.cs b/src/FormBuilder/Models/Fields/NumericField.cs
similarity index 78%
rename from src/FormBuilder/Models/NumericField.cs
rename to src/FormBuilder/Models/Fields/NumericField.cs
index 2f710e6..dbedf37 100644
--- a/src/FormBuilder/Models/NumericField.cs
+++ b/src/FormBuilder/Models/Fields/NumericField.cs
@@ -11,7 +11,6 @@ public NumericField()
else if (typeof(T) == typeof(uint) || typeof(T) == typeof(ulong) || typeof(T) == typeof(ushort))
{
Type = FieldType.NumericInt;
- Min = 0;
}
else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float))
{
@@ -24,9 +23,17 @@ public NumericField()
}
public override FieldType Type { get; }
- public decimal? Min { get; set; }
- public decimal? Max { get; set; }
public string Step { get; set; } = "1";
public bool ShowUpDown { get; set; } = true;
public string? Format { get; set; }
+
+ public decimal? GetMin()
+ {
+ return Validators.OfType().FirstOrDefault()?.Min;
+ }
+
+ public decimal? GetMax()
+ {
+ return Validators.OfType().FirstOrDefault()?.Max;
+ }
}
diff --git a/src/FormBuilder/Models/SelectField.cs b/src/FormBuilder/Models/Fields/SelectField.cs
similarity index 100%
rename from src/FormBuilder/Models/SelectField.cs
rename to src/FormBuilder/Models/Fields/SelectField.cs
diff --git a/src/FormBuilder/Models/TextField.cs b/src/FormBuilder/Models/Fields/TextField.cs
similarity index 50%
rename from src/FormBuilder/Models/TextField.cs
rename to src/FormBuilder/Models/Fields/TextField.cs
index b6da344..1900988 100644
--- a/src/FormBuilder/Models/TextField.cs
+++ b/src/FormBuilder/Models/Fields/TextField.cs
@@ -3,5 +3,9 @@
public class TextField : Field
{
public override FieldType Type => FieldType.Text;
- public long? MaxLength { get; set; }
+
+ public long? GetMaxLength()
+ {
+ return Validators.OfType().FirstOrDefault()?.MaxLength;
+ }
}
diff --git a/src/FormBuilder/Models/ValidatorType.cs b/src/FormBuilder/Models/ValidatorType.cs
deleted file mode 100644
index 39f4681..0000000
--- a/src/FormBuilder/Models/ValidatorType.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace FormBuilder.Models;
-
-public enum ValidatorType
-{
- Required = 1,
- Length = 2,
- Email = 3,
- Range = 4,
-}
diff --git a/src/FormBuilder/Models/EmailValidator.cs b/src/FormBuilder/Models/Validators/EmailValidator.cs
similarity index 100%
rename from src/FormBuilder/Models/EmailValidator.cs
rename to src/FormBuilder/Models/Validators/EmailValidator.cs
diff --git a/src/FormBuilder/Models/LengthValidator.cs b/src/FormBuilder/Models/Validators/LengthValidator.cs
similarity index 100%
rename from src/FormBuilder/Models/LengthValidator.cs
rename to src/FormBuilder/Models/Validators/LengthValidator.cs
diff --git a/src/FormBuilder/Models/NumericRangeValidator.cs b/src/FormBuilder/Models/Validators/NumericRangeValidator.cs
similarity index 60%
rename from src/FormBuilder/Models/NumericRangeValidator.cs
rename to src/FormBuilder/Models/Validators/NumericRangeValidator.cs
index 883f704..de8c8c9 100644
--- a/src/FormBuilder/Models/NumericRangeValidator.cs
+++ b/src/FormBuilder/Models/Validators/NumericRangeValidator.cs
@@ -1,8 +1,8 @@
namespace FormBuilder.Models;
-public class RangeValidator : Validator
+public class NumericRangeValidator : Validator
{
- public override ValidatorType Type => ValidatorType.Range;
+ public override ValidatorType Type => ValidatorType.NumericRange;
public override string Text { get; set; } = "Not in the valid range";
public int Min { get; set; }
public int Max { get; set; }
diff --git a/src/FormBuilder/Models/RequiredValidator.cs b/src/FormBuilder/Models/Validators/RequiredValidator.cs
similarity index 100%
rename from src/FormBuilder/Models/RequiredValidator.cs
rename to src/FormBuilder/Models/Validators/RequiredValidator.cs
diff --git a/src/FormBuilder/Models/Validator.cs b/src/FormBuilder/Models/Validators/Validator.cs
similarity index 100%
rename from src/FormBuilder/Models/Validator.cs
rename to src/FormBuilder/Models/Validators/Validator.cs
diff --git a/src/FormBuilder/Models/Validators/ValidatorType.cs b/src/FormBuilder/Models/Validators/ValidatorType.cs
new file mode 100644
index 0000000..70a7955
--- /dev/null
+++ b/src/FormBuilder/Models/Validators/ValidatorType.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel;
+
+namespace FormBuilder.Models;
+
+public enum ValidatorType
+{
+ [Description("Required Validator")]
+ Required = 1,
+
+ [Description("Length Validator")]
+ Length = 2,
+
+ [Description("Email Validator")]
+ Email = 3,
+
+ [Description("Numeric Range Validator")]
+ NumericRange = 4,
+}