mirror of
https://github.com/PacktPublishing/Web-Development-with-Blazor-Second-Edition.git
synced 2026-04-08 15:54:02 +00:00
Initial commit
This commit is contained in:
parent
2190113c56
commit
3088165398
1765 changed files with 192085 additions and 0 deletions
20
Chapter07/MyBlog/Components/RazorComponents/Alert.razor
Normal file
20
Chapter07/MyBlog/Components/RazorComponents/Alert.razor
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<div class="@($"alert alert-{Style.ToString().ToLower()}")" role="alert">
|
||||
@ChildContent
|
||||
</div>
|
||||
@code{
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; } =@<b>This is a default value</b>;
|
||||
[Parameter]
|
||||
public AlertStyle Style { get; set; }
|
||||
public enum AlertStyle
|
||||
{
|
||||
Primary,
|
||||
Secondary,
|
||||
Success,
|
||||
Danger,
|
||||
Warning,
|
||||
Info,
|
||||
Light,
|
||||
Dark
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
@inject IJSRuntime JSRuntime
|
||||
@implements IDisposable
|
||||
|
||||
<NavigationLock
|
||||
ConfirmExternalNavigation="@(CurrentEditContext.IsModified())"
|
||||
OnBeforeInternalNavigation="OnBeforeInternalNavigation" />
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
public required EditContext CurrentEditContext { get; set; }
|
||||
public string InternalNavigationMessage { get; set; } = "You are about to loose changes, are you sure you want to navigate away?";
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
CurrentEditContext.OnFieldChanged += OnFieldChangedAsync;
|
||||
return base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private async void OnFieldChangedAsync(object? sender,FieldChangedEventArgs args)
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task OnBeforeInternalNavigation(LocationChangingContext context)
|
||||
{
|
||||
if (CurrentEditContext.IsModified())
|
||||
{
|
||||
var isConfirmed = await JSRuntime.InvokeAsync<bool>("confirm",
|
||||
InternalNavigationMessage);
|
||||
|
||||
if (!isConfirmed)
|
||||
{
|
||||
context.PreventNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
CurrentEditContext.OnFieldChanged -= OnFieldChangedAsync;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Microsoft.AspNetCore.Components.Forms;
|
||||
namespace Components;
|
||||
public class BootstrapFieldCssClassProvider : FieldCssClassProvider
|
||||
{
|
||||
public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
|
||||
{
|
||||
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
|
||||
var isModified = editContext.IsModified(fieldIdentifier);
|
||||
return (isModified, isValid) switch
|
||||
{
|
||||
(true, true) => "form-control modified is-valid",
|
||||
(true, false) => "form-control modified is-invalid",
|
||||
(false, true) => "form-control",
|
||||
(false, false) => "form-control"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
namespace Components;
|
||||
|
||||
public class CustomCssClassProvider<ProviderType> : ComponentBase where ProviderType : FieldCssClassProvider, new()
|
||||
{
|
||||
[CascadingParameter]
|
||||
EditContext? CurrentEditContext { get; set; }
|
||||
public ProviderType Provider { get; set; } = new ProviderType();
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (CurrentEditContext == null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(CustomCssClassProvider<ProviderType>)} requires a cascading parameter of type {nameof(EditContext)}. For example, you can use {nameof(CustomCssClassProvider<ProviderType>)} inside an EditForm.");
|
||||
}
|
||||
CurrentEditContext.SetFieldCssClassProvider
|
||||
(Provider);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
namespace Microsoft.AspNetCore.Components.Forms;
|
||||
public class InputTextAreaOnInput :
|
||||
InputBase<string?>
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenElement(0, "textarea");
|
||||
builder.AddMultipleAttributes(1, AdditionalAttributes);
|
||||
builder.AddAttribute(2, "class", CssClass);
|
||||
builder.AddAttribute(3, "value", BindConverter.FormatValue(CurrentValue));
|
||||
builder.AddAttribute(4, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString));
|
||||
builder.CloseElement();
|
||||
}
|
||||
protected override bool TryParseValueFromString(string? value, out string? result, [NotNullWhen(false)] out string? validationErrorMessage)
|
||||
{
|
||||
result = value;
|
||||
validationErrorMessage = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
29
Chapter07/MyBlog/Components/RazorComponents/ItemList.razor
Normal file
29
Chapter07/MyBlog/Components/RazorComponents/ItemList.razor
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
@typeparam ItemType
|
||||
@using System.Collections.Generic
|
||||
<h3>List</h3>
|
||||
<table>
|
||||
<Virtualize Items="@Items" Context="item">
|
||||
<tr>
|
||||
<td>
|
||||
<button class="btn btn-primary" @onclick="@(()=> {SelectEvent.InvokeAsync(item); })"> Select</button>
|
||||
</td>
|
||||
<td>@ItemTemplate(item)</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" @onclick="@(()=> {DeleteEvent.InvokeAsync(item);})"> Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</Virtualize>
|
||||
</table>
|
||||
|
||||
|
||||
@code{
|
||||
[Parameter]
|
||||
public List<ItemType> Items { get; set; } = new List<ItemType>();
|
||||
[Parameter, EditorRequired]
|
||||
public required RenderFragment<ItemType> ItemTemplate { get; set; }
|
||||
[Parameter]
|
||||
public EventCallback<ItemType> DeleteEvent { get; set; }
|
||||
[Parameter]
|
||||
public EventCallback<ItemType> SelectEvent { get; set; }
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue