Blazor 5x - قسمت 14 - کار با فرمها - بخش 2 - تعریف فرمها و اعتبارسنجی آنها
نویسنده: وحید نصیری
تاریخ: ۱۳۹۹/۱۲/۲۰ ۱۲:۳۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
namespace BlazorServer.Services
{
public interface IHotelRoomService
{
Task<HotelRoomDTO> CreateHotelRoomAsync(HotelRoomDTO hotelRoomDTO);
Task<int> DeleteHotelRoomAsync(int roomId);
IAsyncEnumerable<HotelRoomDTO> GetAllHotelRoomsAsync();
Task<HotelRoomDTO> GetHotelRoomAsync(int roomId);
Task<HotelRoomDTO> IsRoomUniqueAsync(string name);
Task<HotelRoomDTO> UpdateHotelRoomAsync(int roomId, HotelRoomDTO hotelRoomDTO);
}
}
@page "/hotel-room"
<div class="row mt-4">
<div class="col-8">
<h4 class="card-title text-info">Hotel Rooms</h4>
</div>
<div class="col-3 offset-1">
<NavLink href="hotel-room/create" class="btn btn-info">Add New Room</NavLink>
</div>
</div>
@code {
} <li class="nav-item px-3">
<NavLink class="nav-link" href="hotel-room">
<span class="oi oi-list-rich" aria-hidden="true"></span> Hotel Rooms
</NavLink>
</li> @page "/hotel-room/create"
<h3>HotelRoomUpsert</h3>
@code {
} <Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<ProjectReference Include="..\BlazorServer.Models\BlazorServer.Models.csproj" />
</ItemGroup>
</Project> @using BlazorServer.Models
@page "/hotel-room/create"
<div class="row mt-2 mb-5">
<h3 class="card-title text-info mb-3 ml-3">@Title Hotel Room</h3>
<div class="col-md-12">
<div class="card">
<div class="card-body">
<EditForm Model="HotelRoomModel">
<div class="form-group">
<label>Name</label>
<InputText @bind-Value="HotelRoomModel.Name" class="form-control"></InputText>
</div>
</EditForm>
</div>
</div>
</div>
</div>
@code
{
private HotelRoomDTO HotelRoomModel = new HotelRoomDTO();
private string Title = "Create";
}
<EditForm Model="HotelRoomModel">
<div class="form-group">
<label>Name</label>
<InputText @bind-Value="HotelRoomModel.Name" class="form-control"></InputText>
</div>
<div class="form-group">
<label>Occupancy</label>
<InputNumber @bind-Value="HotelRoomModel.Occupancy" class="form-control"></InputNumber>
</div>
<div class="form-group">
<label>Rate</label>
<InputNumber @bind-Value="HotelRoomModel.RegularRate" class="form-control"></InputNumber>
</div>
<div class="form-group">
<label>Sq ft.</label>
<InputText @bind-Value="HotelRoomModel.SqFt" class="form-control"></InputText>
</div>
<div class="form-group">
<label>Details</label>
<InputTextArea @bind-Value="HotelRoomModel.Details" class="form-control"></InputTextArea>
</div>
<div class="form-group">
<button class="btn btn-primary">@Title Room</button>
<NavLink href="hotel-room" class="btn btn-secondary">Back to Index</NavLink>
</div>
</EditForm>
<EditForm Model="HotelRoomModel" OnSubmit="HandleHotelRoomUpsert">
</EditForm>
@code
{
private HotelRoomDTO HotelRoomModel = new HotelRoomDTO();
private async Task HandleHotelRoomUpsert()
{
}
} <EditForm Model="HotelRoomModel" OnValidSubmit="HandleHotelRoomUpsert">
<DataAnnotationsValidator />
@*<ValidationSummary />*@
<div class="form-group">
<label>Name</label>
<InputText @bind-Value="HotelRoomModel.Name" class="form-control"></InputText>
<ValidationMessage For="()=>HotelRoomModel.Name"></ValidationMessage>
</div>
<div class="form-group">
<label>Occupancy</label>
<InputNumber @bind-Value="HotelRoomModel.Occupancy" class="form-control"></InputNumber>
<ValidationMessage For="()=>HotelRoomModel.Occupancy"></ValidationMessage>
</div>
<div class="form-group">
<label>Rate</label>
<InputNumber @bind-Value="HotelRoomModel.RegularRate" class="form-control"></InputNumber>
<ValidationMessage For="()=>HotelRoomModel.RegularRate"></ValidationMessage>
</div>
@using BlazorServer.Services
@page "/hotel-room/create"
@inject IHotelRoomService HotelRoomService
@inject NavigationManager NavigationManager
@code
{
private HotelRoomDTO HotelRoomModel = new HotelRoomDTO();
private string Title = "Create";
private async Task HandleHotelRoomUpsert()
{
var roomDetailsByName = await HotelRoomService.IsRoomUniqueAsync(HotelRoomModel.Name);
if (roomDetailsByName != null)
{
//there is a duplicate room. show an error msg.
return;
}
var createdResult = await HotelRoomService.CreateHotelRoomAsync(HotelRoomModel);
NavigationManager.NavigateTo("hotel-room");
}
}
@page "/hotel-room"
@inject IHotelRoomService HotelRoomService
<div class="row mt-4">
<div class="col-8">
<h4 class="card-title text-info">Hotel Rooms</h4>
</div>
<div class="col-3 offset-1">
<NavLink href="hotel-room/create" class="btn btn-info">Add New Room</NavLink>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
<th>Occupancy</th>
<th>Rate</th>
<th>
Sqft
</th>
<th>
</th>
</tr>
</thead>
<tbody>
@if (HotelRooms.Any())
{
foreach (var room in HotelRooms)
{
<tr>
<td>@room.Name</td>
<td>@room.Occupancy</td>
<td>@room.RegularRate.ToString("c")</td>
<td>@room.SqFt</td>
<td></td>
</tr>
}
}
else
{
<tr>
<td colspan="5">No records found</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@code
{
private List<HotelRoomDTO> HotelRooms = new List<HotelRoomDTO>();
protected override async Task OnInitializedAsync()
{
await foreach(var room in HotelRoomService.GetAllHotelRoomsAsync())
{
HotelRooms.Add(room);
}
}
} public class Employee
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[ValidateComplexType]
public Department Department { get; set; } = new Department();
}
public class Department
{
[Required]
public string DepartmentName { get; set; }
} <EditForm Model="@Employee">
<ObjectGraphDataAnnotationsValidator />
<InputText Id="name" Class="form-control" @bind-Value="@Model.Department.DepartmentName"></InputText>
<ValidationMessage For="@(() => Model.Department.DepartmentName)" />
</EditForm> public class EditEmployeeModel
{
public string Email { get; set; }
[CompareProperty("Email",
ErrorMessage = "Email and Confirm Email must match")]
public string ConfirmEmail { get; set; }
} using System.ComponentModel.DataAnnotations;
namespace CustomValidators
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
public class EmailDomainValidator : ValidationAttribute
{
public string AllowedDomain { get; set; }
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
string[] strings = value.ToString().Split('@');
if (strings[1].ToUpper() == AllowedDomain.ToUpper())
{
return null;
}
return new ValidationResult($"Domain must be {AllowedDomain}",
new[] { validationContext.MemberName });
}
}
} public class Employee
{
[EmailDomainValidator(AllowedDomain = "site.com")]
public string Email { get; set; }
} @implements IDisposable
<EditForm EditContext="@_editContext" OnValidSubmit="submit">
<button type="submit" disabled="@_isInvalidForm">Submit</button>
</EditForm>
@code
{
private User _userModel = new User();
private EditContext _editContext;
private bool _isInvalidForm = true;
protected override void OnInitialized()
{
_editContext = new EditContext(_userModel);
_editContext.OnFieldChanged += HandleFieldChanged;
}
private void submit()
{
if(_editContext.Validate())
{
}
}
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
{
_isInvalidForm = !_editContext.Validate();
StateHasChanged();
}
public void Dispose()
{
_editContext.OnFieldChanged -= HandleFieldChanged;
}
} var isValid = !_editContext.GetValidationMessages(fieldIdentifier).Any();
<EditForm Model="NewPerson" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<div class="form-group">
<label for="firstname">First Name</label>
<InputText @bind-Value="NewPerson.FirstName" class="form-control" id="firstname" />
<ValidationMessage For="NewPerson.FirstName" />
</div> protected abstract bool TryParseValueFromString(string value, out T result, out string validationErrorMessage);
@inherits InputBase<string>
<input type="password" @bind="@CurrentValue" class="@CssClass" />
@code {
protected override bool TryParseValueFromString(string value, out string result,
out string validationErrorMessage)
{
result = value;
validationErrorMessage = null;
return true;
}
} <EditForm Model="userInfo" OnValidSubmit="CreateUser">
<DataAnnotationsValidator />
<InputPassword class="form-control" @bind-Value="@userInfo.Password" /> The attribute names could not be inferred from bind attribute 'bind-value'. Bind attributes should be of the form 'bind' or 'bind-value' along with their corresponding optional parameters like 'bind-value:event', 'bind:format' etc.
class="modified valid form-control"
class="modified invalid form-control"
EditContext = new EditContext(Model); EditContext.SetFieldCssClassProvider(new BootstrapFieldCssClassProvider());
using System;
using System.Linq;
using Microsoft.AspNetCore.Components.Forms;
namespace BlazorComponents
{
/// <summary>
/// Supplies CSS class names for form fields to represent their validation state or other state information from an EditContext.
/// </summary>
public class BootstrapFieldCssClassProvider : FieldCssClassProvider
{
/// <summary>
/// Gets a string that indicates the status of the specified field as a CSS class.
/// </summary>
public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
{
if (editContext == null)
{
throw new ArgumentNullException(nameof(editContext));
}
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
if (editContext.IsModified(fieldIdentifier))
{
return isValid ? "is-valid" : "is-invalid";
}
return isValid ? "" : "is-invalid";
}
}
} @"<script>alert('xss')</script><div onload=""alert('xss')"""
+ @"style=""background-color: rgba(0, 0, 0, 1)"">Test<img src=""test.png"""
+ @"style=""background-image: url(javascript:alert('xss')); margin: 10px""></div>"; @model ProjectName.ViewModels.Identity.RegisterViewModel <label asp-for="PhoneNumber"></label>
@using System.Reflection
@using System.Linq.Expressions
@using System.ComponentModel.DataAnnotations
@typeparam T
@if (ChildContent is null)
{
<label>@Label</label>
}
else
{
<label>
@Label
@ChildContent
</label>
}
@code {
[Parameter, EditorRequired]
public Expression<Func<T>> DisplayNameFor { get; set; } = default!;
[Parameter]
public RenderFragment? ChildContent { get; set; }
private string Label => GetDisplayName();
private string GetDisplayName()
{
var expression = (MemberExpression)DisplayNameFor.Body;
var value = expression.Member.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
return value?.Name ?? expression.Member.Name;
}
} private LoginDto Login { get; } = new(); <CustomDisplayName DisplayNameFor="@(() => Login.UserName)" />
<CustomDisplayName DisplayNameFor="@(() => Login.UserName)">
<span class="text-danger">(*)</span>
</CustomDisplayName> @using System.Reflection
@using System.Linq.Expressions;
@using System.ComponentModel.DataAnnotations;
@typeparam T
@if (ChildContent == null)
{
<label>@Label</label>
}
else
{
<label>
@Label
@ChildContent
</label>
}
@code {
[Parameter]
public Expression<Func<T>> DisplayNameFor { get; set; } = default!;
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Inject]
public IStringLocalizerFactory LocalizerFactory { get; set; } = default!;
private string Label => GetDisplayName();
private string GetDisplayName()
{
var expression = (MemberExpression)DisplayNameFor.Body;
var displayAttribute = expression.Member.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
if (displayAttribute is {ResourceType: not null })
{
// Try to dynamically create an instance of the specified resource type
var resourceType = displayAttribute.ResourceType;
var localizer = LocalizerFactory.Create(resourceType);
return localizer[displayAttribute.Name ?? expression.Member.Name];
}
return displayAttribute?.Name ?? expression.Member.Name;
}
} public class LoginDto
{
[Display(Name = nameof(LoginDtoResource.UserName), ResourceType = typeof(LoginDtoResource))]
[Required]
[MaxLength(100)]
public string UserName { get; set; } = default!;
//...
} [Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> InputAttributes { get; set; } = new(); @if (ChildContent is null)
{
<label @attributes="InputAttributes">
@Label
</label>
}
else
{
<label @attributes="InputAttributes">
@Label
@ChildContent
</label>
} <CustomDisplayName DisplayNameFor="@(() => Login.UserName)" class="form-label" id="test" for="UserName" />