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

Commit

Permalink
Merge pull request #15 from chris579/master
Browse files Browse the repository at this point in the history
v1.1.4
  • Loading branch information
klemmchr authored Oct 12, 2019
2 parents 4fcc759 + 876d8fa commit 1fdcfab
Show file tree
Hide file tree
Showing 33 changed files with 697 additions and 91 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,29 @@ public int CurrentCount
#### Lifecycle methods
View models have access to the same lifecycle methods as a component when they are set as a binding context. They are documented [here](https://docs.microsoft.com/en-us/aspnet/core/blazor/components?view=aspnetcore-3.0#lifecycle-methods).

#### Parameters
Parameters are automatically populated to the view model. Declare a parameter in your component

```csharp
@code {
[Parameter]
public string Name { get; set; }
}
```

and declare the same parameter in your view model

```csharp
class ViewModel: ViewModelBase
{
[Parameter]
public string Name { get; set; }
}
```

The parameter will be passed before `OnInitialized` and `OnInitializedAsync` are invoked. Therefore, the parameters are available from any lifecycle method.
You can't access them in your constructor and you're not supposed to do that either.

#### Dispose
View models are implementing the [`IDisposable` pattern of Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/components?view=aspnetcore-3.0#component-disposal-with-idisposable). Inside ViewModels, Disposing is achieved by overriding the `Dispose(bool disposing)` method.

Expand Down
4 changes: 2 additions & 2 deletions samples/BlazorSample/Client/BlazorSample.Client.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Exe</OutputType>
<LangVersion>7.3</LangVersion>
<RazorLangVersion>3.0</RazorLangVersion>
Expand Down
1 change: 0 additions & 1 deletion samples/BlazorSample/Client/Pages/Clock.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@page "/clock"
@using System.Globalization
@inherits MvvmComponentBase<ClockViewModel>

<h1>Clock</h1>
Expand Down
2 changes: 1 addition & 1 deletion samples/BlazorSample/Client/Pages/FetchData.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@inherits MvvmComponentBase<FetchDataViewModel>

<h1>Weather forecast</h1>

<div class="alert alert-primary" role="alert">
To use a view model with your component simply inherit from the base class
<pre style="display: inline">MvvmComponentBase</pre> and specify your view model type for this component as a generic argument.
Expand Down
27 changes: 27 additions & 0 deletions samples/BlazorSample/Client/Pages/Parameters.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@page "/parameters/{name}"
@inherits MvvmComponentBase<ParametersViewModel>

<h1>Clock</h1>

<div class="alert alert-primary" role="alert">
You can also pass down parameters to your view model. If you set a binding context you can
declare your parameters just as you would before but you also declare them in your view model.
They will be passed down to it automatically.
</div>

<p>My Name is @Bind(x => x.Name).</p>

<form class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<label for="newName" class="sr-only">New name</label>
<input class="form-control" id="newName" @bind="@BindingContext.NewName"/>
</div>
<button type="button" class="btn btn-primary mb-2" @onclick="@BindingContext.NavigateToNewName">Navigate</button>
</form>

@code {

[Parameter]
public string Name { get; set; }

}
5 changes: 5 additions & 0 deletions samples/BlazorSample/Client/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<span class="oi oi-clock" aria-hidden="true"></span> Clock
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="parameters/Max Foobar">
<span class="oi oi-link-intact" aria-hidden="true"></span> Parameters
</NavLink>
</li>
</ul>
</div>

Expand Down
1 change: 1 addition & 0 deletions samples/BlazorSample/Client/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddTransient<FetchDataViewModel>();
services.AddTransient<CounterViewModel>();
services.AddTransient<ClockViewModel>();
services.AddTransient<ParametersViewModel>();
}

public void Configure(IComponentsApplicationBuilder app)
Expand Down
2 changes: 1 addition & 1 deletion samples/BlazorSample/Client/ViewModel/ClockViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private void TimerOnElapsed(object sender, ElapsedEventArgs e)

protected override void Dispose(bool disposing)
{
if(disposing)
if (disposing)
_timer.Dispose();
}
}
Expand Down
27 changes: 27 additions & 0 deletions samples/BlazorSample/Client/ViewModel/ParametersViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Components;
using MvvmBlazor.ViewModel;

namespace BlazorSample.Client.ViewModel
{
public class ParametersViewModel : ViewModelBase
{
private readonly NavigationManager _navigationManager;

public ParametersViewModel(NavigationManager navigationManager)
{
_navigationManager = navigationManager;
}

[Parameter] public string Name { get; set; }

public string NewName { get; set; }

public void NavigateToNewName()
{
if (string.IsNullOrEmpty(NewName))
return;

_navigationManager.NavigateTo($"/parameters/{NewName}");
}
}
}
27 changes: 27 additions & 0 deletions samples/BlazorServersideSample/Pages/Parameters.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@page "/parameters/{name}"
@inherits MvvmComponentBase<ParametersViewModel>

<h1>Clock</h1>

<div class="alert alert-primary" role="alert">
You can also pass down parameters to your view model. If you set a binding context you can
declare your parameters just as you would before but you also declare them in your view model.
They will be passed down to it automatically.
</div>

<p>My Name is @Bind(x => x.Name).</p>

<form class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<label for="newName" class="sr-only">New name</label>
<input class="form-control" id="newName" @bind="@BindingContext.NewName" />
</div>
<button type="button" class="btn btn-primary mb-2" @onclick="@BindingContext.NavigateToNewName">Navigate</button>
</form>

@code {

[Parameter]
public string Name { get; set; }

}
5 changes: 5 additions & 0 deletions samples/BlazorServersideSample/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<span class="oi oi-clock" aria-hidden="true"></span> Clock
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="parameters/Max Foobar">
<span class="oi oi-link-intact" aria-hidden="true"></span> Parameters
</NavLink>
</li>
</ul>
</div>

Expand Down
3 changes: 2 additions & 1 deletion samples/BlazorServersideSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddTransient<FetchDataViewModel>();
services.AddTransient<CounterViewModel>();
services.AddTransient<ClockViewModel>();
services.AddTransient<ParametersViewModel>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -53,7 +54,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
Expand Down
2 changes: 1 addition & 1 deletion samples/BlazorServersideSample/ViewModel/ClockViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private void TimerOnElapsed(object sender, ElapsedEventArgs e)

protected override void Dispose(bool disposing)
{
if(disposing)
if (disposing)
_timer.Dispose();
}
}
Expand Down
27 changes: 27 additions & 0 deletions samples/BlazorServersideSample/ViewModel/ParametersViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Components;
using MvvmBlazor.ViewModel;

namespace BlazorServersideSample.ViewModel
{
public class ParametersViewModel : ViewModelBase
{
private readonly NavigationManager _navigationManager;

public ParametersViewModel(NavigationManager navigationManager)
{
_navigationManager = navigationManager;
}

[Parameter] public string Name { get; set; }

public string NewName { get; set; }

public void NavigateToNewName()
{
if (string.IsNullOrEmpty(NewName))
return;

_navigationManager.NavigateTo($"/parameters/{NewName}");
}
}
}
1 change: 1 addition & 0 deletions samples/BlazorServersideSample/_Imports.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@using BlazorServersideSample
@using BlazorServersideSample.Shared
Expand Down
37 changes: 34 additions & 3 deletions src/MvvmBlazor.Tests/Components/MvvmComponentBaseTTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using MvvmBlazor.Components;
using MvvmBlazor.Internal.Bindings;
using MvvmBlazor.Internal.Parameters;
using MvvmBlazor.Internal.WeakEventListener;
using MvvmBlazor.ViewModel;
using Shouldly;
Expand All @@ -22,10 +24,13 @@ public class MvvmComponentBaseTTests
var serviceProvider = new Mock<IServiceProvider>();
var wemf = new Mock<IWeakEventManagerFactory>();
var bindingFactory = new Mock<IBindingFactory>();
var viewModelParameterSetter = new Mock<IViewModelParameterSetter>();
serviceProvider.Setup(x => x.GetService(typeof(ViewModelBase))).Returns(viewModel.Object);
serviceProvider.Setup(x => x.GetService(typeof(IWeakEventManagerFactory))).Returns(wemf.Object);
serviceProvider.Setup(x => x.GetService(typeof(IWeakEventManagerFactory))).Returns(wemf.Object);
serviceProvider.Setup(x => x.GetService(typeof(IBindingFactory))).Returns(bindingFactory.Object);
serviceProvider.Setup(x => x.GetService(typeof(IViewModelParameterSetter))).Returns(viewModelParameterSetter.Object);
serviceProvider.Setup(x => x.GetService(typeof(Mock<IViewModelParameterSetter>))).Returns(viewModelParameterSetter);

return (viewModel, serviceProvider);
}
Expand Down Expand Up @@ -81,7 +86,7 @@ public Task ParametersAsync(ParameterView parameters)
public void AfterRender_CalledOnBindingContext()
{
var (viewModel, serviceProvider) = GetServiceProvider();

var component = new MockMvvmComponentBase(serviceProvider.Object);
component.AfterRender(true);

Expand Down Expand Up @@ -154,8 +159,6 @@ public void Dispose_DisposesBindingContext()
[Fact]
public void OnInitialized_CalledOnBindingContext()
{
var task = new Task(() => { });

var (viewModel, serviceProvider) = GetServiceProvider();

var component = new MockMvvmComponentBase(serviceProvider.Object);
Expand All @@ -165,6 +168,34 @@ public void OnInitialized_CalledOnBindingContext()
viewModel.VerifyNoOtherCalls();
}

[Fact]
public void OnInitialized_SetsViewModelParameters()
{
var (viewModel, serviceProvider) = GetServiceProvider();
var viewModelParameterSetter =
serviceProvider.Object.GetRequiredService<Mock<IViewModelParameterSetter>>();

var component = new MockMvvmComponentBase(serviceProvider.Object);
component.Initialized();

viewModelParameterSetter.Verify(x => x.ResolveAndSet(component, viewModel.Object));
viewModelParameterSetter.VerifyNoOtherCalls();
}

[Fact]
public void OnParametersSet_SetsViewModelParameters()
{
var (viewModel, serviceProvider) = GetServiceProvider();
var viewModelParameterSetter =
serviceProvider.Object.GetRequiredService<Mock<IViewModelParameterSetter>>();

var component = new MockMvvmComponentBase(serviceProvider.Object);
component.ParametersSet();

viewModelParameterSetter.Verify(x => x.ResolveAndSet(component, viewModel.Object));
viewModelParameterSetter.VerifyNoOtherCalls();
}

[Fact]
public void OnInitializedAsync_CalledOnBindingContext()
{
Expand Down
Loading

0 comments on commit 1fdcfab

Please sign in to comment.