angularjs入門-$http
建立DB的資料和預設內容
angularjs的$http其實本身就有很多東西可以說,比如像promises或$q甚至是專支援restful特性的ngresource,但這系列其實只是入門,我也並不打算在此篇能包山包海的去談,這系列入門其實只是希望給還不會angularjs的人,可以有一個入門的方向,所以不會涉獵太深,未來有機會再多寫一點記錄,但因為我們需要使用$http去呼叫web api,所以在這邊我打算先從web api和code first去建立一個後端來進行互動,首先我們先開起vs,然後選擇web api的方案,我這邊是vs2013,我直接就選擇web api專案,如下圖
然後我想先把identity給取消掉,選擇Change Authentication,然後選擇No Authentication,接下按下ok
接下來我先選擇nuget,然後下載EntityFramework還有angularjs
接著我直接在Models新增一個students的類別,程式碼如下
接著我在Models再新增一支DefaultContext的類別,程式碼如下
using System.Collections.Generic;
using System.Data.Entity;
namespace WebApiDemo.Models
{
public class DefaultContext : DbContext
{
public DefaultContext()
: base("DefaultConnection")
{
Database.SetInitializer<DefaultContext>(new DefaultDataInit());
}
public DbSet<Student> Student { get; set; }
}
}
我在Models下又新增了一支DefaultDataInit.cs,因為我希望在顯示的時候,可以先在db塞點預設的資料,需要實作CreateDatabaseIfNotExists,這個則是代表如果沒有資料的話,會先建立預設的資料,程式碼如下
using System.Data.Entity;
using System.Data.Entity.Migrations;
namespace WebApiDemo.Models
{
public class DefaultDataInit:CreateDatabaseIfNotExists<DefaultContext>
{
public override void InitializeDatabase(DefaultContext context)
{
base.InitializeDatabase(context);
context.Student.AddOrUpdate(x => x.Name,
new Student() { Name = "王小明", PhoneNumber = "0915808888", Address = "台中市" },
new Student() { Name = "王大明", PhoneNumber = "0915801111", Address = "台北市" },
new Student() { Name = "王大雄", PhoneNumber = "0915806666", Address = "台南市" },
new Student() { Name = "王小雄", PhoneNumber = "0915800000", Address = "新北市" },
new Student() { Name = "王小安", PhoneNumber = "0915807777", Address = "桃園市" }
);
context.SaveChanges();
}
}
}
然後我們需要在web.config設定連線字串,我在此是用DefaultConnection,請把連線改成您自己的,我自己有建立另外一個執行個體,所以是MSSQL,預設則會是v11.0,這邊使用的是localdb方便本機測試,如下
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQL;Initial Catalog=AngularjsDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
</connectionStrings>
接著請打開Package Manager Console
然後首先輸入enable-migrations,第二個指令則是輸入add-migration init,最後是update-database,這時候我們就已經建立了db在您預設的位置
建立Web API部份
在來就是WebApi的部份,我在這部份就是把預設的ValuesController改掉,下是就是簡單的示例
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApiDemo.Models;
namespace WebApiDemo.Controllers
{
public class ValuesController : ApiController
{
DefaultContext db = new DefaultContext();
// GET api/values
public IEnumerable<Student> Get()
{
return db.Student.ToList();
}
// POST api/values
public Student Post(Student emp)
{
db.Student.Add(emp);
db.SaveChanges();
return emp;
}
// PUT api/values/5
public void Put(Student emp)
{
db.Entry(emp).State = EntityState.Modified;
db.SaveChanges();
}
// DELETE api/values/5
public void Delete(int id)
{
var emp =db.Student.Find(id);
db.Entry(emp).State = EntityState.Deleted;
db.SaveChanges();
}
}
}
建立前端html和angularjs的部份
接下來就是把angularjs放進Views>Shared>_Layout.cshtml裡面,我把一些不需要的區塊和jquery等等拿掉,只留我想要的,如下圖
接著我新加了App的資料夾,裡面新增一支Index.js,預計要來寫angularjs的程式碼,然後我就直接修改預設的HomeController的Index,程式碼如下
Home/Index.cshtml
<div class="row" ng-controller="FirstCtrl as firstCtrl">
<div ng-switch="View">
<div ng-switch-default>
<table class="table">
<tr>
<th>姓名</th>
<th>電話</th>
<th>地址</th>
</tr>
<tr ng-repeat="item in firstCtrl.student">
<td>{{item.Name}}</td>
<td>{{item.PhoneNumber}}</td>
<td>{{item.Address}}</td>
</tr>
</table>
</div>
</div>
</div>
@section scripts{
<script src="~/App/Index.js"></script>
}
在這邊我先只做顯示的部份,之後會再加上新刪修的功能示範,接下來看一下index.js的程式碼
angular.module('MyApp', [])
.controller('FirstCtrl', function ($http) {
var Url = 'http://localhost:65414/Api/'
var vm = this;
$http.get(Url + 'Values').success(function (data) {
vm.Student = data;
}).error(function () {
alert('發生錯誤');
});
});
請注意一下,因為我們需要用到$http,所以需要注入進來此controller
Url是您自己的網址,$http.get則是angularjs的快捷指令,success的話之後回調的值不一定要全部填上,也可以只需要填寫data,也可以取名成自己想要的命名,然後error也就是發生錯誤的時候要做什麼處理,接著就是展現出來的畫面
至此我們已經順利的從後端取資料顯示出來了
實做新增功能
我在html新增了兩顆按鈕,分別是新增和儲存,如下
Index.cshtml
<div class="row" ng-controller="FirstCtrl as firstCtrl">
<div class="row">
<input type="button" value="新增" class="btn btn-default" ng-click="firstCtrl.AddClick()" />
<input type="button" value="儲存" class="btn btn-default" ng-click="firstCtrl.SaveClick()" ng-disabled="!firstCtrl.SaveState" />
</div>
<br />
<div class="row">
<div ng-switch="firstCtrl.View">
<div ng-switch-when="add">
姓名:<input type="text" ng-model="firstCtrl.Add.Name" class="form-control" />
電話:<input type="text" ng-model="firstCtrl.Add.PhoneNumber" class="form-control" />
地址:<input type="text" ng-model="firstCtrl.Add.Address" class="form-control" />
</div>
<div ng-switch-default>
<table class="table">
<tr>
<th>姓名</th>
<th>電話</th>
<th>地址</th>
</tr>
<tr ng-repeat="item in firstCtrl.Student">
<td>{{item.Name}}</td>
<td>{{item.PhoneNumber}}</td>
<td>{{item.Address}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
@section scripts{
<script src="~/App/Index.js"></script>
}
Index.js
angular.module('MyApp', [])
.controller('FirstCtrl', function ($http,$scope) {
var Url = 'http://localhost:65414/Api/'
var errorMessage = '發生錯誤';
var vm = this;
$http.get(Url + 'Values').success(function (data) {
vm.Student = data;
}).error(function () {
alert(errorMessage);
})
vm.AddClick = function () {
vm.View = 'add';
vm.SaveState = true;
} //改變狀態切換到add同時把儲存按鈕變成可以編輯
vm.SaveClick = function () {
$http.post(Url + 'Values',vm.Add).success(function (data) { //vm.Add是html的input值
vm.Student.push(data); //這一段我是直接從web api回傳單筆資料回來,然後直接對陣列新增,就沒在從資料庫把值取回來
vm.View = 'list'; //因為如果沒有相符就是default的狀態,所以我給list或null值都可以
}).error(function () {
alert(errorMessage);
})
}
});
因為程式碼有點多,所以我把說明直接寫在註解裡面,方便理解各行程式碼在做什麼事情
實做刪除和修改功能
這邊我在對原有的html和js加上刪修和修改功能,如下
Index.cshtml
<div class="row" ng-controller="FirstCtrl as firstCtrl">
<div class="row">
<input type="button" value="新增" class="btn btn-default" ng-click="firstCtrl.AddClick()" ng-hide="firstCtrl.AddHide" />
<input type="button" value="儲存" class="btn btn-default" ng-click="firstCtrl.SaveClick()" ng-disabled="!firstCtrl.SaveState" />
</div>
<br />
<div class="row">
<div ng-switch="firstCtrl.View">
<div ng-switch-when="add">
<h3>新增</h3>
姓名:<input type="text" ng-model="firstCtrl.Add.Name" class="form-control" />
電話:<input type="text" ng-model="firstCtrl.Add.PhoneNumber" class="form-control" />
地址:<input type="text" ng-model="firstCtrl.Add.Address" class="form-control" />
</div>
<div ng-switch-when="edit">
<h3>修改</h3>
<span ng-init="firstCtrl.Edit.ID"></span>
姓名:<input type="text" ng-model="firstCtrl.Edit.Name" class="form-control" />
電話:<input type="text" ng-model="firstCtrl.Edit.PhoneNumber" class="form-control" />
地址:<input type="text" ng-model="firstCtrl.Edit.Address" class="form-control" />
</div>
<div ng-switch-default>
<table class="table">
<tr>
<th></th>
<th>姓名</th>
<th>電話</th>
<th>地址</th>
</tr>
<tr ng-repeat="item in firstCtrl.Student">
<td>
<input type="button" value="修改" class="btn btn-default" ng-click="firstCtrl.EditClick(item)" />
<input type="button" value="刪除" class="btn btn-default" ng-click="firstCtrl.DeleteClick(item.ID,$index)" />
</td>
<td>{{item.Name}}</td>
<td>{{item.PhoneNumber}}</td>
<td>{{item.Address}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
@section scripts{
<script src="~/App/Index.js"></script>
}
Index.js
angular.module('MyApp', [])
.controller('FirstCtrl', function ($http,$scope) {
var Url = 'http://localhost:65414/Api/'
var errorMessage = '發生錯誤';
var vm = this;
$http.get(Url + 'Values').success(function (data) {
vm.Student = data;
}).error(function () {
alert(errorMessage);
})
vm.AddClick = function () {
vm.View = 'add';
vm.SaveState = true;
} //改變狀態切換到add同時把儲存按鈕變成可以編輯
vm.SaveClick = function () {
if (vm.View === 'add') { //判斷ng-switch狀態,因為我用同一個儲存按鈕同時做新增和修改動作
$http.post(Url + 'Values', vm.Add).success(function (data) { //vm.Add是html的input值
vm.Student.push(data); //這一段我是直接從web api回傳單筆資料回來,然後直接對陣列新增,就沒在從資料庫把值取回來
vm.View = 'list'; //因為如果沒有相符就是default的狀態,所以我給list或null值都可以
vm.SaveState = false; //把儲存按鈕切換成不可編輯的狀態
}).error(function () {
alert(errorMessage);
})
} else {
$http.put(Url + 'Values', vm.Edit).success(function () { //vm.Edit是html裡的input值
vm.View = 'list';
vm.SaveState = false;
}).error(function () {
alert(errorMessage);
})
}
}
vm.EditClick = function (item) {
vm.View = 'edit';
vm.SaveState = true;
vm.Edit = item;
}
vm.DeleteClick = function (ID,Index) { //ID是從前端傳過來,為了丟到後端做刪除動作,Index則是我要直接刪除陣列,不在從後端傳來資料
$http.delete(Url + 'Values/'+ID).success(function () {
vm.Student.splice(Index);
}).error(function () {
alert(errorMessage);u
})
}
});
整個操作的示意畫面大約如下
總結
以上最主要是示範$http的做法,不過實際上我們在做表單還需要考慮到前端驗證的部份,所以正規來說我們會使用ng-submit來實做,但如果要放在同一篇來解釋,文章會變得非常長,所以留著下一篇再解釋,這邊程式碼比較多,所以我會在底下放個github的原始碼,可下載原始碼回去查看,然後試著run看看,需注意一下,connection需要改成自己的連線,以上再請多多指教。