Skip to content
This repository has been archived by the owner on Nov 1, 2024. It is now read-only.

Commit

Permalink
State improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
YuriyDurov committed May 5, 2024
1 parent 981a5ce commit aad14eb
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@

<h1>Counter</h1>

<p>This page is currently being rendered using: @(OperatingSystem.IsBrowser() ? "WASM" : "Server")</p>
<p>Current render mode: @RenderingEnvironment</p>

@if (ViewModel.State is not null)
{
<p>@ViewModel.State.Text</p>
<p>@ViewModel.State?.Text</p>

<p role="status">Current count: @ViewModel.State.Count</p>
<p role="status">Current count: @ViewModel.State?.Count</p>

<button class="btn btn-primary" @onclick="ViewModel.IncrementCount">Click me</button>
}
<button class="btn btn-primary" @onclick="ViewModel.IncrementCount">Click me</button>

@{
base.BuildRenderTree(__builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@

public class CounterPageViewModel : ComponentViewModel<CounterPageViewModelState>
{
private readonly Timer _timer;

public CounterPageViewModel()
{
_timer = new Timer(TimerIncrementCount, null, 1000, 1000);
}

private void TimerIncrementCount(object? state)
{
State.Count++;
StateHasChanged();
}

public override void InitializeState()
{
State.Count = 0;
State.Text = "ViewModel State initialized on: " + (OperatingSystem.IsBrowser() ? "Client" : "Server");
State.Text = $"ViewModel State initialized on: {RenderingEnvironment}";
}

public void IncrementCount()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public static class AddRenderingEnvironmentExtension
{
public static IServiceCollection AddRenderingEnvironment(this IServiceCollection services)
{
services.AddTransient(x => x.GetRenderingEnvironment());
services.AddScoped(x => x.GetRenderingEnvironment());

return services;
}
Expand Down
6 changes: 6 additions & 0 deletions src/BitzArt.Blazor.MVVM/Interfaces/IStateComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace BitzArt.Blazor.MVVM;

internal interface IStateComponent
{
public void StateHasChanged();
}
8 changes: 5 additions & 3 deletions src/BitzArt.Blazor.MVVM/Models/ComponentViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
/// </summary>
public abstract class ComponentViewModel
{
public delegate void StateChangedEventHandler();
public event StateChangedEventHandler? StateChanged;
internal IStateComponent Component { get; set; } = null!;

protected internal RenderingEnvironment RenderingEnvironment { get; internal set; } = null!;

/// <summary>
/// Notifies the component that the state has changed.
/// </summary>
protected void StateHasChanged()
{
StateChanged?.Invoke();
Component.StateHasChanged();
}
}

Expand All @@ -24,6 +25,7 @@ protected void StateHasChanged()
public abstract class ComponentViewModel<TState> : ComponentViewModel, IStatefulViewModel
where TState : class, new()
{

/// <summary>
/// Persistent state of this view model.
/// </summary>
Expand Down
11 changes: 6 additions & 5 deletions src/BitzArt.Blazor.MVVM/Models/PageBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace BitzArt.Blazor.MVVM;
/// Blazor page base class with view model support.
/// </summary>
/// <typeparam name="TViewModel">Type of this component's ViewModel</typeparam>
public abstract partial class PageBase<TViewModel> : ComponentBase
public abstract partial class PageBase<TViewModel> : ComponentBase, IStateComponent
where TViewModel : ComponentViewModel
{
private const string StateKey = "state";
Expand All @@ -25,7 +25,7 @@ public abstract partial class PageBase<TViewModel> : ComponentBase
private IJSRuntime Js { get; set; } = default!;

[Inject]
private RenderingEnvironment RenderingEnvironment { get; set; } = null!;
protected RenderingEnvironment RenderingEnvironment { get; set; } = null!;

/// <summary>
/// Navigation manager.
Expand All @@ -48,10 +48,9 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
/// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns>
protected override async Task OnInitializedAsync()
{
ViewModel.StateChanged += StateHasChanged;

await base.OnInitializedAsync();

ViewModel.Component = this;
ViewModel.RenderingEnvironment = RenderingEnvironment;
await RestoreStateAsync();
}

Expand Down Expand Up @@ -119,6 +118,8 @@ public override Task SetParametersAsync(ParameterView parameters)

return base.SetParametersAsync(parameters);
}

void IStateComponent.StateHasChanged() => InvokeAsync(StateHasChanged);
}

internal static class StateJsonOptionsProvider
Expand Down
11 changes: 11 additions & 0 deletions src/BitzArt.Blazor.MVVM/Models/RenderingEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,15 @@ public class RenderingEnvironment
public required bool IsPrerender { get; init; }
public required bool IsServer { get; init; }
public required bool IsClient { get; init; }

public override string ToString()
{
if (IsClient) return "Client";
if (IsServer)
{
if (IsPrerender) return "Server (prerender)";
return "Server";
}
return "Unknown";
}
}

0 comments on commit aad14eb

Please sign in to comment.