1. 概述
本文将带你快速掌握如何使用 AngularJS 实现一个前端应用,用于消费 RESTful API。
核心功能包括:数据列表展示、新增资源、更新和删除操作。整个过程简洁直接,适合已有 AngularJS 和 REST 基础的开发者参考。
✅ 目标:实现对 Feed
资源的增删改查(CRUD)
⚠️ 注意:本文不讲 AngularJS 基础语法,聚焦于与后端 API 的对接实践
2. REST API 接口设计
我们先来看后端暴露的 REST 接口,管理 Feed
资源,支持分页:
- 获取分页列表:
GET /api/myFeeds?page={page}&size={size}&sortDir={dir}&sort={propertyName}
- 创建 Feed:
POST /api/myFeeds
- 更新 Feed:
PUT /api/myFeeds/{id}
- 删除 Feed:
DELETE /api/myFeeds/{id}
分页参数说明:
page
:当前页码(从 0 开始)size
:每页条数sort
:排序字段名sortDir
:排序方向(asc
或desc
)
示例 Feed
数据结构:
{
"id": 1,
"name": "baeldung feed",
"url": "/feed"
}
⚠️ 注意:page
参数后端是 0 起始,前端 ng-table
是 1 起始,需要转换
3. 页面结构(HTML)
前端页面使用 ng-table
展示数据,并提供增删改入口:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-resource.min.js"></script>
<script th:src="@{/resources/ng-table.min.js}"></script>
<script th:src="@{/resources/mainCtrl.js}"></script>
<a href="#" ng-click="addNewFeed()">Add New RSS Feed</a>
<table ng-table="tableParams">
<tr ng-repeat="row in $data track by row.id">
<td data-title="'Name'" sortable="'name'">{{row.name}}</td>
<td data-title="'Feed URL'" sortable="'url'">{{row.url}}</td>
<td data-title="'Actions'">
<a href="#" ng-click="editFeed(row)">Edit</a>
<a href="#" ng-click="confirmDelete(row.id)">Delete</a>
</td>
</tr>
</table>
✅ 关键点:
- 引入
angular.min.js
和angular-resource.min.js
- 使用
ng-table
实现可排序、可分页的表格 - 操作按钮绑定
ng-click
事件
4. Angular 控制器初始化
控制器定义模块并注入依赖:
var app = angular.module('myApp', ["ngTable", "ngResource"]);
app.controller('mainCtrl', function($scope, NgTableParams, $resource) {
// 实现逻辑见下文
});
✅ 依赖说明:
ngTable
:用于数据表格展示与分页控制ngResource
:用于封装 REST API 调用,比$http
更语义化
5. 配置 ng-table 数据源
ng-table
的核心是 NgTableParams
,我们通过 getData
自定义数据获取逻辑,适配后端分页格式:
$scope.feed = $resource("api/myFeeds/:feedId", {feedId: '@id'});
$scope.tableParams = new NgTableParams({}, {
getData: function(params) {
var queryParams = {
page: params.page() - 1, // 转换为 0 起始
size: params.count()
};
var sortingProp = Object.keys(params.sorting());
if (sortingProp.length == 1) {
queryParams["sort"] = sortingProp[0];
queryParams["sortDir"] = params.sorting()[sortingProp[0]];
}
return $scope.feed.query(queryParams, function(data, headers) {
var totalRecords = headers("PAGING_INFO").split(",")[0].split("=")[1];
params.total(totalRecords);
return data;
}).$promise;
}
});
⚠️ 踩坑提醒:
params.page()
返回的是 1 起始,需减 1 适配后端params.sorting()
返回{name: 'asc'}
,需拆解为sort
和sortDir
- 总记录数通过响应头
PAGING_INFO
获取,格式如:total=100,page=0
✅ query()
返回数组,适合列表;get()
返回单个对象
6. CRUD 操作实现
6.1 新增 Feed
使用 $resource
的 save()
方法发起 POST
请求:
$scope.feed = {name: "New feed", url: "http://www.example.com/feed"};
$scope.createFeed = function() {
$scope.feeds.save($scope.feed, function() {
$scope.tableParams.reload();
});
}
✅ 注意:save()
默认对应 POST
,无需额外配置
6.2 更新 Feed
$resource
默认没有 update
方法,需手动定义:
$scope.feeds = $resource("api/myFeeds/:feedId", {feedId: '@id'}, {
'update': { method: 'PUT' }
});
$scope.updateFeed = function() {
$scope.feeds.update($scope.feed, function() {
$scope.tableParams.reload();
});
}
✅ 技巧:{feedId: '@id'}
表示 URL 中的 feedId
从数据对象的 id
字段取值
6.3 删除 Feed
调用 delete()
方法发送 DELETE
请求:
$scope.confirmDelete = function(id) {
$scope.feeds.delete({feedId: id}, function() {
$scope.tableParams.reload();
});
}
✅ 注意:参数对象用于填充 URL 模板,非请求体
7. 使用 ngDialog 实现弹窗
使用 ngDialog
模块实现新增/编辑弹窗,避免页面跳转。
弹窗模板
<script type="text/ng-template" id="templateId">
<div class="ngdialog-message">
<h2>{{feed.name}}</h2>
<input ng-model="feed.name"/>
<input ng-model="feed.url"/>
</div>
<div class="ngdialog-buttons mt">
<button ng-click="save()">Save</button>
</div>
</script>
控制器逻辑
$scope.addNewFeed = function() {
$scope.feed = {name: "New Feed", url: ""};
ngDialog.open({ template: 'templateId', scope: $scope });
}
$scope.editFeed = function(row) {
$scope.feed = angular.copy(row);
ngDialog.open({ template: 'templateId', scope: $scope });
}
$scope.save = function() {
ngDialog.close('ngdialog1');
if (!$scope.feed.id) {
$scope.createFeed();
} else {
$scope.updateFeed();
}
}
✅ 说明:
addNewFeed
初始化空对象editFeed
使用angular.copy()
避免直接修改原数据save()
根据是否存在id
判断是新增还是更新
8. 全局错误处理
避免每个请求都写 error callback
,使用 $httpProvider
拦截器统一处理错误:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q, $rootScope) {
return {
responseError: function(responseError) {
$rootScope.message = responseError.data.message;
return $q.reject(responseError);
}
};
});
}]);
页面展示错误信息
<div ng-show="message" class="alert alert-danger">
{{message}}
</div>
✅ 优势:
- 集中处理 4xx/5xx 响应
- 通过
$rootScope.message
全局通知 - 用户体验更友好
9. 总结
本文通过一个简单的 Feed
管理前端,演示了 AngularJS 如何高效对接 RESTful API。
核心要点回顾:
- 使用
ngResource
封装 CRUD,语义清晰 ng-table
轻松实现分页排序,但需注意参数适配ngDialog
提升交互体验- 拦截器实现全局错误处理,减少重复代码
完整代码已开源,可直接导入运行:
👉 GitHub 项目地址:https://github.com/baeldung/reddit-app
🔧 环境:Eclipse 项目,Maven 构建,导入即用
适合用于学习或作为小型管理后台的快速原型参考。