ASP.NET Core View Components MVC
▌Introduction
In my opinion,
View Components is very similar to Partial View in rendering them
to the HTML. However, View Components executes the InvokeAsync
function before passing a model to the View. (We will talk about this later.)
▋Not reachable directly as an HTTP
endpoint, they are invoked from your code (usually in a view). A view component
never handles a request.
▋View component classes can be
contained in any folder in the project.
▋It can uses dependency injection.
▋InvokeAsync exposes a method which
can be called from a view, and it can take an arbitrary number of arguments.
▌Environment
▋Visual Studio 2015
Update 3
▋NPM: 3.10.3
▋Microsoft.AspNetCore.Mvc
1.0.0
▌Implement
▋Create controller/view
Before we deep into View Components, create the
controller and view as following.
▋CustomerVcController
[Area("Basic")]
[Route("Basic/[controller]/[action]")]
public class CustomerVcController : Controller
{
public IActionResult Index()
{
return View();
}
}
|
We will implement View later.
▋ViewComplonent : Default view
We could create the Default view in either
Views\CustomerVc\Components\[View Component
name]\Default.cshtml
Or
Views\Shared\Components\[View Component name]\Default.cshtml
The View Component will return the Default.cshtml as View in default.
▋ Default.cshtml
@model List<Angular2.Mvc.Core.Models.ViewModel.VmCustomer>
<div class="alert alert-info" role="alert">
@{
var title = "Hi, " + ViewBag.Description;
}
@title
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model
=> model.First().Name)
</th>
<th>
@Html.DisplayNameFor(model
=> model.First().Age)
</th>
<th>
@Html.DisplayNameFor(model
=> model.First().Phone)
</th>
<th>
@Html.DisplayNameFor(model
=> model.First().Description)
</th>
<th></th>
</tr>
</thead>
<tbody>
@if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td class="col-sm-2">
@(new
Microsoft.AspNetCore.Html.HtmlString(item.Name))
</td>
<td class="col-sm-2">
@Html.DisplayFor(modelItem
=> item.Age)
</td>
<td class="col-sm-1">
@Html.DisplayFor(modelItem
=> item.Phone)
</td>
<td class="col-sm-2">
@Html.DisplayFor(modelItem
=> item.Description)
</td>
</tr>
}
}
</tbody>
</table>
|
▋ViewComplonent : class
Notice that ViewComponent
classe can be put in any folder in the project.
I put it in the path just
like controllers and views.
▋CustomerViewComponent.cs
[ViewComponent(Name = "CustomerVc")]
public class CustomerViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(int? id, string name)
{
var items = await this.getCustomersAsync(id,
name);
ViewBag.Description = "this view is
from ViewComponent.";
return View(items); //Return Default.cshtml
}
private async Task<List<VmCustomer>>
getCustomersAsync(int? id, string name)
{
//return something
}
}
|
PS.
The
ViewComponent name is “Customer” with the suffix “ViewComponent” of “CustomerViewComponent”
being removed.
We can specify the ViewComponent name by the Attribute:
[ViewComponent(Name = "")]
Okay, we had implemented the ViewComponent, let us see
how to use it in View or Controller.
▋Use ViewComponent in View
▋index.cshtml
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
@await Component.InvokeAsync("CustomerVc", new { name = "JB" })
</div>
|
Notice that
View Components are still RENDERED ON SERVER SIDE, we will later use another
way to render it in ajax way.
▋OR use ViewComponent in Controller
public IActionResult IndexVc()
{
return ViewComponent("CustomerVc", new { name = "JB" });
}
|
▋Result
▋ViewComplonent : Return different view
Before the ViewComponent
return a view, we invoke the InvokeAsync() function.
So we could implement some
logics inside the ViewComponent.
Here is a simple application,
we will let ViewComponent return different view which depending on the
parameter value.
First we should create
another view for our ViewComponent.
And then update ViewComponent
class.
▋CustomerVcController.cs
(Update)
public async Task<IViewComponentResult> InvokeAsync(string display, int? id, string name)
{
var items = await this.getCustomersAsync(id,
name);
ViewBag.Description
= "this view is from
ViewComponent.";
if (!string.IsNullOrEmpty(display)
&& display.ToLower().Equals("card"))
return View("Card",
items);
else
return View("Default", items);
}
|
▋Index.cshtml
(Update)
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
@await
Component.InvokeAsync("CustomerVc", new {display="Card", name = "JB" })
</div>
|
▋Result
▋Ajax rendering
We can create a Http method
in Controller and just return the view (HTML) thru ViewComponent. (Just like
returning PartialView!)
▋Controller
[HttpGet]
public IActionResult GetView([FromQuery] string name)
{
return ViewComponent("CustomerVc", new { name = "JB" });
}
|
▋Index.cshtml
<div id="ajaxCust"></div>
|
▋javascript (jquery)
$(function () {
renderViewComponent();
function renderViewComponent()
{
$("#ajaxCust").html("");
$.ajax({
dataType: "html",
url:
getUri + "?name=Leia",
success: function (cust) {
$("#ajaxCust").append(cust);
}
})
}
})
|
▋Result
▌Reference
沒有留言:
張貼留言