mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-03 21:29:20 +00:00
413 lines
12 KiB
C#
413 lines
12 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.Forms;
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
using Radzen.Blazor;
|
|
using Radzen.Blazor.Rendering;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Radzen
|
|
{
|
|
/// <summary>
|
|
/// Class DataBoundFormComponent.
|
|
/// Implements the <see cref="Radzen.RadzenComponent" />
|
|
/// Implements the <see cref="Radzen.IRadzenFormComponent" />
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <seealso cref="Radzen.RadzenComponent" />
|
|
/// <seealso cref="Radzen.IRadzenFormComponent" />
|
|
public class DataBoundFormComponent<T> : RadzenComponent, IRadzenFormComponent
|
|
{
|
|
/// <summary>
|
|
/// Gets or sets the index of the tab.
|
|
/// </summary>
|
|
/// <value>The index of the tab.</value>
|
|
[Parameter]
|
|
public int TabIndex { get; set; } = 0;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the filter case sensitivity.
|
|
/// </summary>
|
|
/// <value>The filter case sensitivity.</value>
|
|
[Parameter]
|
|
public FilterCaseSensitivity FilterCaseSensitivity { get; set; } = FilterCaseSensitivity.Default;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the filter operator.
|
|
/// </summary>
|
|
/// <value>The filter operator.</value>
|
|
[Parameter]
|
|
public StringFilterOperator FilterOperator { get; set; } = StringFilterOperator.Contains;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the name.
|
|
/// </summary>
|
|
/// <value>The name.</value>
|
|
[Parameter]
|
|
public string? Name { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the placeholder.
|
|
/// </summary>
|
|
/// <value>The placeholder.</value>
|
|
[Parameter]
|
|
public string? Placeholder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this <see cref="DataBoundFormComponent{T}"/> is disabled.
|
|
/// </summary>
|
|
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool Disabled { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the change.
|
|
/// </summary>
|
|
/// <value>The change.</value>
|
|
[Parameter]
|
|
public EventCallback<object> Change { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the load data.
|
|
/// </summary>
|
|
/// <value>The load data.</value>
|
|
[Parameter]
|
|
public EventCallback<Radzen.LoadDataArgs> LoadData { get; set; }
|
|
|
|
/// <summary>
|
|
/// The form
|
|
/// </summary>
|
|
IRadzenForm? form;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the form.
|
|
/// </summary>
|
|
/// <value>The form.</value>
|
|
[CascadingParameter]
|
|
public IRadzenForm? Form
|
|
{
|
|
get
|
|
{
|
|
return form;
|
|
}
|
|
set
|
|
{
|
|
form = value;
|
|
form?.AddComponent(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The value
|
|
/// </summary>
|
|
private T? _value;
|
|
/// <summary>
|
|
/// Gets or sets the value.
|
|
/// </summary>
|
|
/// <value>The value.</value>
|
|
[Parameter]
|
|
public T? Value
|
|
{
|
|
get
|
|
{
|
|
return _value;
|
|
}
|
|
set
|
|
{
|
|
if (value == null || value.Equals("null"))
|
|
{
|
|
_value = default;
|
|
return;
|
|
}
|
|
|
|
if (!value.Equals(_value))
|
|
_value = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value changed.
|
|
/// </summary>
|
|
/// <value>The value changed.</value>
|
|
[Parameter]
|
|
public EventCallback<T> ValueChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether this instance is bound.
|
|
/// </summary>
|
|
/// <value><c>true</c> if this instance is bound; otherwise, <c>false</c>.</value>
|
|
public bool IsBound
|
|
{
|
|
get
|
|
{
|
|
return ValueChanged.HasDelegate;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets a value indicating whether this instance has value.
|
|
/// </summary>
|
|
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
|
|
public virtual bool HasValue
|
|
{
|
|
get
|
|
{
|
|
if (typeof(T) == typeof(string))
|
|
{
|
|
return !string.IsNullOrEmpty($"{Value}");
|
|
}
|
|
return Value != null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the text property.
|
|
/// </summary>
|
|
/// <value>The text property.</value>
|
|
[Parameter]
|
|
public string? TextProperty { get; set; }
|
|
|
|
/// <summary>
|
|
/// The data
|
|
/// </summary>
|
|
IEnumerable? _data;
|
|
/// <summary>
|
|
/// Gets or sets the data.
|
|
/// </summary>
|
|
/// <value>The data.</value>
|
|
[Parameter]
|
|
public virtual IEnumerable? Data
|
|
{
|
|
get
|
|
{
|
|
return _data;
|
|
}
|
|
set
|
|
{
|
|
if (_data != value)
|
|
{
|
|
_view = null;
|
|
_value = default;
|
|
_data = value;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when [data changed].
|
|
/// </summary>
|
|
protected virtual async Task OnDataChanged()
|
|
{
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the query.
|
|
/// </summary>
|
|
/// <value>The query.</value>
|
|
protected virtual IQueryable? Query
|
|
{
|
|
get
|
|
{
|
|
return Data != null ? Data.AsQueryable() : null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the search text
|
|
/// </summary>
|
|
[Parameter]
|
|
public string? SearchText
|
|
{
|
|
get
|
|
{
|
|
return searchText;
|
|
}
|
|
set
|
|
{
|
|
if (searchText != value)
|
|
{
|
|
searchText = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the search text changed.
|
|
/// </summary>
|
|
/// <value>The search text changed.</value>
|
|
[Parameter]
|
|
public EventCallback<string> SearchTextChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// The search text
|
|
/// </summary>
|
|
internal string? searchText;
|
|
|
|
/// <summary>
|
|
/// The view
|
|
/// </summary>
|
|
protected IQueryable? _view;
|
|
/// <summary>
|
|
/// Gets the view.
|
|
/// </summary>
|
|
/// <value>The view.</value>
|
|
protected virtual IEnumerable? View
|
|
{
|
|
get
|
|
{
|
|
var query = Query;
|
|
if (_view == null && query != null)
|
|
{
|
|
if (!string.IsNullOrEmpty(searchText) && !string.IsNullOrEmpty(TextProperty))
|
|
{
|
|
_view = query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
|
}
|
|
else
|
|
{
|
|
_view = Data is IQueryable ? query.Cast<object>().ToList().AsQueryable() : query;
|
|
}
|
|
}
|
|
|
|
return _view;
|
|
}
|
|
}
|
|
|
|
internal IEnumerable? GetView() => View;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the edit context.
|
|
/// </summary>
|
|
/// <value>The edit context.</value>
|
|
[CascadingParameter]
|
|
public EditContext? EditContext { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets the field identifier.
|
|
/// </summary>
|
|
/// <value>The field identifier.</value>
|
|
[Parameter]
|
|
public FieldIdentifier FieldIdentifier { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value expression.
|
|
/// </summary>
|
|
/// <value>The value expression.</value>
|
|
[Parameter]
|
|
public Expression<Func<T>>? ValueExpression { get; set; }
|
|
/// <summary>
|
|
/// Set parameters as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="parameters">The parameters.</param>
|
|
/// <returns>A Task representing the asynchronous operation.</returns>
|
|
public override async Task SetParametersAsync(ParameterView parameters)
|
|
{
|
|
// check for changes before setting the properties through the base call
|
|
var dataChanged = parameters.DidParameterChange(nameof(Data), Data);
|
|
var disabledChanged = parameters.DidParameterChange(nameof(Disabled), Disabled);
|
|
|
|
// allow the base class to process parameters and set the properties
|
|
// after this call the parameters object should be considered stale
|
|
await base.SetParametersAsync(parameters);
|
|
|
|
// handle changes
|
|
if (dataChanged)
|
|
{
|
|
await OnDataChanged();
|
|
}
|
|
|
|
if (EditContext != null && (ValueExpression != null || ValueChanged.HasDelegate) && FieldIdentifier.Model != EditContext.Model)
|
|
{
|
|
FieldIdentifier = ValueExpression != null
|
|
? FieldIdentifier.Create(ValueExpression)
|
|
: FieldIdentifier.Create(() => Value);
|
|
EditContext.OnValidationStateChanged -= ValidationStateChanged;
|
|
EditContext.OnValidationStateChanged += ValidationStateChanged;
|
|
}
|
|
|
|
if (disabledChanged)
|
|
{
|
|
FormFieldContext?.DisabledChanged(Disabled);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validations the state changed.
|
|
/// </summary>
|
|
/// <param name="sender">The sender.</param>
|
|
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
|
|
private void ValidationStateChanged(object? sender, ValidationStateChangedEventArgs e)
|
|
{
|
|
StateHasChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes this instance.
|
|
/// </summary>
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
|
|
if (EditContext != null)
|
|
{
|
|
EditContext.OnValidationStateChanged -= ValidationStateChanged;
|
|
}
|
|
|
|
Form?.RemoveComponent(this);
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value.
|
|
/// </summary>
|
|
/// <returns>System.Object.</returns>
|
|
public virtual object? GetValue()
|
|
{
|
|
return Value;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the class list.
|
|
/// </summary>
|
|
/// <param name="className">Name of the class.</param>
|
|
/// <returns>ClassList.</returns>
|
|
protected ClassList GetClassList(string className) => ClassList.Create(className)
|
|
.AddDisabled(Disabled)
|
|
.Add(FieldIdentifier, EditContext)
|
|
.Add("rz-state-empty", !HasValue);
|
|
|
|
/// <inheritdoc/>
|
|
public virtual async ValueTask FocusAsync()
|
|
{
|
|
await Element.FocusAsync();
|
|
}
|
|
|
|
/// <summary> Provides support for RadzenFormField integration. </summary>
|
|
[CascadingParameter]
|
|
public IFormFieldContext? FormFieldContext { get; set; }
|
|
|
|
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
|
protected string? CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
|
|
|
/// <summary>
|
|
/// Handles the ContextMenu event.
|
|
/// </summary>
|
|
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
|
/// <returns>Task.</returns>
|
|
public override Task OnContextMenu(MouseEventArgs args)
|
|
{
|
|
if (!Disabled)
|
|
{
|
|
return base.OnContextMenu(args);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|