如何將ViewModel從後端傳遞至AngularJS Controller中進行繫結
前言
在使用ASP.Net MVC開發時,通常會依據View中所需資訊定義一個View Model作為頁面資料繫結之用,因此就可以在後端Controller中賦予View Model特定內容,接著將View Model傳入View後,利用檢視頁面Model強型別的特性,搭配HtmlHelper來呈現View Model中各屬性之資料內容。
當前端套用AngularJS框架後,在View設計上就很少會使用HtmlHelper擴充方法來產生匹配物件屬性的Html了,而是自行建立Html元素並利用AngularJS所提供的ng-model Directive作資料繫結設定。如此是否表示View中所宣告@model(View Model)已無用武之地? 其實不然,我們還是可以利用後端Controller將View Model資料傳入View中的機制,讓AngularJS繫結機制幫忙呈現View Model資料做為畫面初始值;有興趣的朋友可以參考以下做法來實現。
實作說明
以用戶資訊編輯功能為例,首先定義用戶資訊類別(User)作為編輯畫面View Model使用
{
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
}
接著Controller中模擬取得該User資料作為View Model,並傳送至View中顯示資料內容
{
public class HomeController : Controller
{
public ActionResult Edit(string userId)
{
// 模擬取得該userId之用戶資料
var viewModel = new User()
{
UserId = "Chris",
Name = "Chris Chen",
Address = "Taiwan Taipei..."
};
// 傳出ViewModel至頁面
return View(viewModel);
}
}
}
若使用ASP.Net MVC進行資料繫結的View如下。主要先宣告此頁面使用的View Model為User類別,接著就可以透過HtmlHelper幫忙產出對應View Model中各屬性所需之Html代碼,並且將值賦予至各元素中,而產出的Html元素名稱(Name)將做為資料回傳伺服端資料綁定之依據。
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>User</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.UserId)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
產出前端畫面如下(ViewModel屬性值皆繫結[via ASP.Net MVC]至頁面上)
當前端要套用AngularJS框架時,首先會在JS檔中建立module及controller如下。
由於我們可以在View中獲得從後端Controller傳入之View Model資料,因此直接將此頁面繫結的View Model(User)資料內容轉換成JSON格式,並以此資料建立viewModel Value Provider供後續注入前端AngularJS controller中使用。
接著就可以在前端controller中注入viewModel了。先將viewModel資料存入controller的editUser屬性中。
.module('app', [ ]);
angular
.module('app')
.controller("UserController", function (viewModel) {
var vm = this;
// set viewModel as editUser
vm.editUser = viewModel;
// edit user via web api
vm.Edit = function () {
//...
}
});
經過前面的努力後,前端controller的editUser屬性就是後端Controller傳入View中的View Model(User)資料,因此我們就可以依照View Model(User)資料結構來設定各Input元素的ng-model資訊如下。
<div class="form-horizontal" ng-controller="UserController as ctrl">
<h4>User</h4>
<hr />
<div class="form-group">
<label class="control-label col-md-2" for="Name">Name</label>
<div class="col-md-10">
<input type="text" ng-model="ctrl.editUser.Name" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Address">Address</label>
<div class="col-md-10">
<input type="text" ng-model="ctrl.editUser.Address" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Save" ng-click="ctrl.Edit()" class="btn btn-default" />
</div>
</div>
</div>
@section Scripts {
<script>
// 將Model轉換成JSON
var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model));
// 建立 viewModel Value Provider 供後續注入controller使用
angular.module('app').value("viewModel", model);
</script>
}
執行後前端畫面如下(ViewModel屬性值皆繫結[via AngularJS]至頁面上),實現了我們的需求。
參考資料
http://davideguida.altervista.org/angularjs-mvc-how-to-pass-model-from-server-to-angular-controller/
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !