Skip to content

Commit

Permalink
🆕 feat(Form): add the ValidateOn parameter to support setting the val…
Browse files Browse the repository at this point in the history
…idation timing (#2080)

* 🆕 feat(Form): add the ValidateOn parameter to support setting the validation timing

* 🐛 fix(Slider): tab key to focus is not working
  • Loading branch information
capdiem committed Aug 8, 2024
1 parent 1898ee5 commit 55a991b
Show file tree
Hide file tree
Showing 16 changed files with 85 additions and 74 deletions.
11 changes: 2 additions & 9 deletions src/Masa.Blazor/Components/Form/FormContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,13 @@ public FormContext(EditContext editContext, MForm form)
/// <summary>
/// parse form validation result,if parse failed throw exception
/// </summary>
/// <param name="validationResult">
/// validation result
/// see details https://blazor.masastack.com/components/forms
/// </param>
/// <param name="validationResult"></param>
public void ParseFormValidation(string validationResult) => Form.ParseFormValidation(validationResult);

/// <summary>
/// parse form validation result,if parse failed return false
/// </summary>
/// <param name="validationResult">
/// validation result
/// see details https://blazor.masastack.com/components/forms
/// </param>
/// <returns></returns>
/// <param name="validationResult"></param>
public bool TryParseFormValidation(string validationResult) => Form.TryParseFormValidation(validationResult);

public void ParseFormValidation(IEnumerable<ValidationResult> validationResults) =>
Expand Down
15 changes: 5 additions & 10 deletions src/Masa.Blazor/Components/Form/MForm.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public partial class MForm : MasaComponentBase
[MasaApiParameter(true, ReleasedOn = "v1.7.0")]
public bool AutoLabel { get; set; } = true;

[Parameter] public ValidateOn ValidateOn { get; set; } = ValidateOn.Input;

internal ConcurrentDictionary<string, string> AutoLabelMap { get; } = new();

private static readonly ConcurrentDictionary<Type, PropertyInfo[]> s_modelPropertiesMap = new();
Expand All @@ -52,7 +54,7 @@ public partial class MForm : MasaComponentBase

/// <summary>
/// The type of property attribute used to generate the label,
/// the default value is same as <see cref="FFormAutoLabelOptionsAttributeType"/>.
/// the default value is same as <see cref="AutoLabelOptions.AttributeType"/>.
/// </summary>
internal Type? LabelAttributeType { get; set; } = typeof(DisplayNameAttribute);

Expand Down Expand Up @@ -221,10 +223,7 @@ public bool Validate(FieldIdentifier fieldIdentifier)
/// <summary>
/// parse form validation result,if parse faield throw exception
/// </summary>
/// <param name="validationResult">
/// validation result
/// see deatils https://blazor.masastack.com/components/forms
/// </param>
/// <param name="validationResult"></param>
[MasaApiPublicMethod]
public void ParseFormValidation(string validationResult)
{
Expand All @@ -235,11 +234,7 @@ public void ParseFormValidation(string validationResult)
/// <summary>
/// parse form validation result,if parse failed return false
/// </summary>
/// <param name="validationResult">
/// validation result
/// see deatils https://blazor.masastack.com/components/forms
/// </param>
/// <returns></returns>
/// <param name="validationResult"></param>
[MasaApiPublicMethod]
public bool TryParseFormValidation(string validationResult)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Masa.Blazor/Components/Form/Validation/ValidateOn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Masa.Blazor;

public enum ValidateOn
{
Input,

Blur,

Submit
}
45 changes: 26 additions & 19 deletions src/Masa.Blazor/Components/Input/MInput.Validatable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ public partial class MInput<TValue> : IInputJsCallbacks, IValidatable
{
[Inject] private InputJSModule InputJSModule { get; set; } = null!;

[CascadingParameter] public MForm? Form { get; set; }

[CascadingParameter] public EditContext? EditContext { get; set; }

[Parameter] public bool Disabled { get; set; }

[Parameter] public bool Readonly { get; set; }
Expand All @@ -25,10 +29,6 @@ public virtual TValue? Value

[Parameter] public Expression<Func<TValue>>? ValueExpression { get; set; }

[CascadingParameter] public MForm? Form { get; set; }

[CascadingParameter] public EditContext? EditContext { get; set; }

[Parameter] public bool Error { get; set; }

[Parameter] public int ErrorCount { get; set; } = 1;
Expand Down Expand Up @@ -145,6 +145,19 @@ public List<string> ValidationTarget

public virtual bool IsReadonly => Readonly || Form is { Readonly: true };

public ValidateOn ValidateOn
{
get
{
if (IsDirtyParameter(nameof(ValidateOnBlur)))
{
return ValidateOnBlur ? ValidateOn.Blur : ValidateOn.Input;
}

return Form?.ValidateOn ?? ValidateOn.Input;
}
}

public virtual bool ShouldValidate
{
get
Expand All @@ -154,9 +167,9 @@ public virtual bool ShouldValidate
return true;
}

if (ValidateOnBlur)
if (ValidateOn == ValidateOn.Blur)
{
return HasFocused && !IsFocused;
return HasFocused;
}

return HasInput || HasFocused;
Expand Down Expand Up @@ -210,7 +223,7 @@ public virtual async Task HandleOnInputAsync(ChangeEventArgs args)
}
}

if (!ValidateOnBlur)
if (ValidateOn == ValidateOn.Input)
{
//We removed NextTick since it doesn't trigger render
//and validate may not be called
Expand Down Expand Up @@ -263,7 +276,8 @@ private async void IsFocusedChangeCallback(bool val)
if (!val && !IsDisabled)
{
HasFocused = true;
if (ValidateOnBlur)

if (ValidateOn == ValidateOn.Blur)
{
InternalValidate();
}
Expand Down Expand Up @@ -330,16 +344,9 @@ protected virtual void OnInternalValueChange(TValue? val)
// mark it with hasInput
HasInput = true;

if (ValidateOnlyInFocusedState)
{
if (HasFocused)
{
NextTickIf(InternalValidate, () => !ValidateOnBlur);
}
}
else
if (ValidateOn == ValidateOn.Input)
{
NextTickIf(InternalValidate, () => !ValidateOnBlur);
NextTick(InternalValidate);
}

if (_internalValueChangingFromOnValueChanged)
Expand All @@ -353,8 +360,8 @@ protected virtual void OnInternalValueChange(TValue? val)
_ = SetValueByJsInterop(Formatter(val));
}

_ = ValueChanged.InvokeAsync(val.TryDeepClone());
}
_ = ValueChanged.InvokeAsync(val.TryDeepClone());
}
}

protected virtual void SubscribeValidationStateChanged()
Expand Down
5 changes: 3 additions & 2 deletions src/Masa.Blazor/Components/Input/MInput.razor
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
@ChildContent
};

protected virtual RenderFragment GenLabel(bool preventDefaultOnClick = false) => __builder =>
protected virtual RenderFragment GenLabel(bool preventDefaultOnClick = false, bool stopPropagationOnClick = false) => __builder =>
{
if (HasLabel)
{
Expand All @@ -160,7 +160,8 @@
Focused="@HasState"
For="@Id"
Light="@Light"
@onclick:preventDefault="@preventDefaultOnClick">
__internal_stopPropagation_onclick="@stopPropagationOnClick"
__internal_preventDefault_onclick="@preventDefaultOnClick">
@RenderFragments.RenderFragmentOrText(LabelContent, ComputedLabel, wrapperTag: null)
</MLabel>
}
Expand Down
20 changes: 6 additions & 14 deletions src/Masa.Blazor/Components/Radio/MRadio.razor
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
@namespace Masa.Blazor
@inherits MasaComponentBase
@using StyleBuilder = Masa.Blazor.Core.StyleBuilder
@typeparam TValue

<CascadingValue Value="IsDark" Name="IsDark">
<div class="@GetClass()"
style="@GetStyle()"
id="@Id"
@ref="Ref"
@onclick="@HandleClick"
@attributes="@Attributes">
<div class="@_selectionControls.Element("input")">
@ref="Ref">
<div class="@_selectionControls.Element("input").AppendClasses(CssClassUtils.GetTextColor(RippleState))" ripple>

<MIcon Icon="@(IsActive ? OnIcon : OffIcon)"
Dense="@(RadioGroup?.Dense is true)"
Expand All @@ -23,21 +19,17 @@
checked="@IsActive"
value="@Value"
@onblur="OnBlur"
@onchange="OnChange"
@onchange="@HandleOnChange"
@onfocus="OnFocus"
@onkeydown="OnKeyDown"
@onclick:stopPropagation/>

@RenderFragments.GenRipple(
Ripple,
GetClass(_selectionControls.Element("ripple").Name, CssClassUtils.GetTextColor(RippleState)),
StyleBuilder.Create().AddTextColor(RippleState).Build())
@onclick:stopPropagation
@attributes="@Attributes"/>
</div>

<MLabel For="@Id"
Color="@ValidationState"
Focused="@HasState"
@onclick:preventDefault>
@onclick:stopPropagation>
@RenderFragments.RenderFragmentOrText(LabelContent, Label, wrapperTag: null)
</MLabel>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/Masa.Blazor/Components/Radio/MRadio.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ protected bool IsDark

protected bool IsReadonly => Readonly || RadioGroup?.IsReadonly is true;

private async Task HandleClick(MouseEventArgs args)
private async Task HandleOnChange()
{
if (IsDisabled || IsReadonly || IsActive)
{
Expand Down
5 changes: 3 additions & 2 deletions src/Masa.Blazor/Components/Radio/MRadioGroup.razor
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
};


protected override RenderFragment GenLabel(bool preventDefaultOnClick = false) => __builder =>
protected override RenderFragment GenLabel(bool preventDefaultOnClick = false, bool stopPropagationOnClick = false) => __builder =>
{
if (HasLabel)
{
Expand All @@ -30,7 +30,8 @@
Light="@Light"
Id="@Id"
Tag="legend"
@onclick:preventDefault="@preventDefaultOnClick">
__internal_stopPropagation_onclick="@stopPropagationOnClick"
__internal_preventDefault_onclick="@preventDefaultOnClick">
@RenderFragments.RenderFragmentOrText(LabelContent, ComputedLabel, wrapperTag: null)
</MLabel>
}
Expand Down
3 changes: 1 addition & 2 deletions src/Masa.Blazor/Components/Slider/MSliderBase.razor
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@
@attributes="@ThumbAttrs"
@onfocus="@(e => HandleOnFocusAsync(index, e))"
@onblur="@(e => HandleOnBlurAsync(index, e))"
@onkeydown="@HandleOnKeyDownAsync"
@onkeydown:preventDefault>
@onkeydown="@HandleOnKeyDownAsync">

@GenThumb()

Expand Down
5 changes: 3 additions & 2 deletions src/Masa.Blazor/Components/TextField/MTextField.razor
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@RenderFragments.GenProgress(Loading, Color, LoaderHeight, ProgressContent)
};

protected override RenderFragment GenLabel(bool preventDefaultOnClick = false) => __builder =>
protected override RenderFragment GenLabel(bool preventDefaultOnClick = false, bool stopPropagationOnClick = false) => __builder =>
{
if (ShowLabel)
{
Expand All @@ -38,7 +38,8 @@
Light="@Light"
Value="@LabelValue"
@ref="@LabelReference"
@onclick:preventDefault="@preventDefaultOnClick">
__internal_stopPropagation_onclick="@stopPropagationOnClick"
__internal_preventDefault_onclick="@preventDefaultOnClick">
@RenderFragments.RenderFragmentOrText(LabelContent, ComputedLabel, wrapperTag: null)
</MLabel>
}
Expand Down
4 changes: 2 additions & 2 deletions src/Masa.Blazor/Components/TextField/MTextField.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public virtual bool Outlined

public bool HasCounter => Counter != false && Counter != null;

public override string ComputedColor
public override string? ComputedColor
{
get
{
Expand Down Expand Up @@ -618,7 +618,7 @@ private void UpdateValue(string? originValue, bool succeeded, TValue? convertedV
}
}

if (!ValidateOnBlur)
if (ValidateOn == ValidateOn.Input)
{
//We removed NextTick since it doesn't trigger render
//and validate may not be called
Expand Down
2 changes: 1 addition & 1 deletion src/Masa.Blazor/Mixins/Selectable/MSelectable.razor
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<div class="@ControlBlock.Element("input")" ripple>
@GenSelection()
</div>
@GenLabel(true)
@GenLabel(false, true)
};

protected virtual RenderFragment? GenSelection() => default;
Expand Down
2 changes: 1 addition & 1 deletion src/Masa.Blazor/Mixins/Selectable/MSelectable.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public partial class MSelectable<TValue> : MInput<TValue> where TValue : notnull

public override bool HasColor => IsActive;

public override string ComputedColor => Color ?? (IsDark && !AppIsDark ? "white" : "primary");
public override string? ComputedColor => Color ?? (IsDark && !AppIsDark ? "white" : "primary");

private bool IsCustomValue => IsDirtyParameter(nameof(TrueValue)) && IsDirtyParameter(nameof(FalseValue));

Expand Down
8 changes: 0 additions & 8 deletions src/Masa.Blazor/wwwroot/css/masa-blazor.css
Original file line number Diff line number Diff line change
Expand Up @@ -22918,10 +22918,6 @@ html.overflow-y-hidden {
.m-input--checkbox.m-input--dense {
margin-top: 4px;
}
.m-input--selection-controls {
margin-top: 16px;
padding-top: 4px;
}
.m-input--selection-controls > .m-input__append-outer,
.m-input--selection-controls > .m-input__prepend-outer {
margin-top: 0;
Expand All @@ -22940,7 +22936,6 @@ html.overflow-y-hidden {
display: inline-flex;
flex: 1 1 auto;
height: auto;
margin-inline-start: 10px;
}
.m-input--selection-controls__input {
color: inherit;
Expand Down Expand Up @@ -27286,9 +27281,6 @@ html.overflow-y-hidden {
.m-input--radio-group--column legend {
padding-bottom: 8px;
}
.m-input--radio-group--column .m-radio:not(:last-child):not(:only-child) {
margin-bottom: 8px;
}
.m-input--radio-group--column .m-input--radio-group__input {
flex-direction: column;
}
Expand Down
Loading

0 comments on commit 55a991b

Please sign in to comment.