AngularJS实例GutHub是一款简单管理应用,主要的特性如下:
1.两列布局
2.在左侧有一个导航条
3.允许你创建新菜谱
4.允许你浏览现有的菜谱列表
主视图位于右侧,主视图将会根据具体的URL刷新,可以显示菜谱列表、菜谱项目详情,以及用来添加或编辑菜谱的表单。
本文源码下载地址:https://github.com/johnnymitrevski/gutHub
工程结构图:
controllers.js
//Setup the GutHub angular module var app = angular.module('guthub', ['guthub.directives', 'guthub.services']); //Update the baseUrl to match the directory the app is deployed on the web server. Leave blank if '/'. var baseUrl = ""; /** * Specify the various routes we have in our application. For each route we specify: * 1) The controller that backs it up. * 2) The template to load. * 3) The resolve object (Optional). This tells angular JS that each of the resolve keys need to be meet * before the route can be displayed to the user. For us, we want to load all the recipe data before we * display the page. If the resolve function returns a $q (promise) then AngularJs is smart enough to wait * for the promise to get resolved before it proceeds. That means wait till the server responds. */ app.config(['$routeProvider', function($routeProvider) { $routeProvider.when('/', { controller: 'ListCtrl', resolve: { recipes: function(MultiRecipeLoader) { return MultiRecipeLoader(); } }, templateUrl: baseUrl + '/GutHub/views/list.html' }).when('/edit/:recipeId', { controller: 'EditCtrl', resolve: { recipe: function(RecipeLoader) { return RecipeLoader(); } }, templateUrl: baseUrl + '/GutHub/views/recipeForm.html' }).when('/view/:recipeId', { controller: 'ViewCtrl', resolve: { recipe: function(RecipeLoader) { return RecipeLoader(); } }, templateUrl: baseUrl + '/GutHub/views/viewRecipe.html' }).when('/new', { controller: 'NewCtrl', templateUrl:baseUrl + '/GutHub/views/recipeForm.html' }).otherwise({redirectTo: '/'}); }]); /** * List the recipes */ app.controller('ListCtrl',['$scope','recipes',function($scope, recipes) { //$scope.recipes = recipes; $scope.recipes = [ { id:1, title:"cookies", description: "Delicious, crisp on the outside, chewy" + " on the outside, oozing with chocolatey goodness " + "cookies. The best kind", ingredients: [ { amount: "1", amountUnits: "packet", ingredientName: "Chips Ahoy" } ], instructions: "1. Go buy a packet of Chips Ahoy\ n" + "2. Heat it up in an oven\ n" + "3. Enjoy warm cookies\ n" + "4. Learn how to bake cookies from somewhere else" } ]; }]); /** * View a recipe */ app.controller('ViewCtrl', ['$scope','$location','recipe', function($scope, $location, recipe) { $scope.recipe = recipe; $scope.edit = function() { $location.path('/edit/' + recipe.id); }; }]); /** * Exposes save() and remove() functions to scope. * * save() will save the current recipe and then redirect to the view screen * of the same recipe. * * remove() removes the recipe from the scope and redirects the uses to the * main landing page. */ app.controller('EditCtrl', ['$scope','$location','recipe', function($scope, $location, recipe) { $scope.recipe = recipe; $scope.save = function() { $scope.recipe.$save(function(recipe){ $location.path(baseUrl + '/GutHub/view/' + recipe.id); }); }; $scope.remove = function() { delete $scope.recipe; //Doesn't remove it from the server. Only from $scope. $location.path(baseUrl + '/'); }; }]); /** * Create a new recipe. */ app.controller('NewCtrl',['$scope', '$location', 'Recipe', function($scope, $location, Recipe){ $scope.recipe = new Recipe({ ingredients: [{}] }); $scope.save = function() { $scope.recipe.$save(function(recipe) { $location.path(baseUrl + '/view/' + recipe.id); }); }; }]); /** * Edit the ingredients. It inherits $scope from the parent controller. */ app.controller('IngredientsCtrl', ['$scope', function($scope) { $scope.addIngredient = function() { var ingredients = $scope.recipe.ingredients; ingredients[ingredients.length] = {}; }; $scope.removeIngredient = function(index) { $scope.recipe.ingredients.splice(index, 1); }; }]);
directives.js
var directives = angular.module('guthub.directives',[]); directives.directive('butterbar',['$rootScope', function($rootScope){ return { link: function(scope, element, attrs) { element.addClass('hide'); //Hide the element upfront //Watch the $routeChangeStart and remove the hide css, therefore show $rootScope.$on('$routeChangeStart', function() { element.removeClass('hide'); }); //Watch the $routeChangeSuccess and remove add the hide css, therefore hide $rootScope.$on('$routeChangeSuccess', function() { element.addClass('hide'); }); } }; }]); /** * Calls the focus() method on the current element. * * Call it by adding the focus attribute on any input element. * i.e. <input type="text" focus></input> * Therefore when the page loads, that element immediately gets the focus. */ directives.directive('focus', function() { return { link: function(scope, element, attrs) { element[0].focus(); } }; });
services.js
var services = angular.module('guthub.services',['ngResource']); /** * Recipe service. * * Uses $resource, which is is a RESTful handle that encapsulates lower level $http service. * * Recipe can now be used an argument injected into our controllers. The following methods are built in: * Recipe.get(); * Recipe.save(); * Recipe.delete(); * Recipe.remove(); * Recipe.delete(); * * Useage: if we pass in an object with an id field, then the value of that field will be * added to the end of the URL. * Calling Recipe.get({id:15}) will make a call to /recipes/15 * * For example: * var recipe = new Recipe(existingRecipeObj); * recipe.$save(); - this calls a POST request */ services.factory('Recipe',['$resource', function($resource){ return $resource('/GutHub/recipes/:id',{id: '@id'}); }]); /** * Load all recipes. */ services.factory('MultiRecipeLoader', ['Recipe', '$q', function(Recipe,$q){ return function() { var delay = $q.defer(); Recipe.query(function(recipesData) { delay.resolve(recipesData); }, function() { //delay.reject('Unable to fetch recipes'); delay.resolve([{id:1, title:"cookies"}, {id:2, title:"farts"}]); }); return delay.promise; }; }]); /** * Load a single recipe. */ services.factory('RecipeLoader', ['Recipe','$route', '$q', function(Recipe, $route, $q){ return function() { var delay = $q.defer(); Recipe.get({id: $route.current.params.recipeId}, function(recipeData) { delay.resolve(recipeData); }, function() { //delay.reject('Unable to fetch recipe ' + $route.current.params.recipeId); delay.resolve({ id:1, title:"cookies", description: "Delicious, crisp on the outside, chewy" + " on the outside, oozing with chocolatey goodness " + "cookies. The best kind", ingredients: [ { amount: "1", amountUnits: "packet", ingredientName: "Chips Ahoy" } ], instructions: "1. Go buy a packet of Chips Ahoy\ n" + "2. Heat it up in an oven\ n" + "3. Enjoy warm cookies\ n" + "4. Learn how to bake cookies from somewhere else" }); }); return delay.promise; } }]);
index.html
<!DOCTYPE html> <html lang="en" ng-app="guthub"> <head> <title>GutHub - Create and Share</title> <script src="scripts/vendor/angular.js"></script> <script src="scripts/vendor/angular-resource.js"></script> <script src="scripts/directives/directives.js"> </script> <script src="scripts/services/services.js"> </script> <script src="scripts/controllers/controllers.js"></script> <link href="scripts/vendor/bootstrap/css/bootstrap.css" rel="stylesheet"> </head> <body> <header> <h1>GutHub</h1> </header> <div butterbar>Loading...</div> <div class="container-fluid"> <div class="row-fluid"> <div class="span2"> <!--Sidebar--> <div id="focus"> <a href="#/new">New Recipe</a> </div> <div> <a href="#/">Recipe List</a> </div> </div> <div class="span10"> <div ng-view></div> </div> </div> </div> </body> </html>
list.html
<h3>Recipe List</h3> <ul class="recipes"> <li ng-repeat="recipe in recipes"> <div> <a href="#/view/{{ recipe.id }}">{{ recipe.title }}</a> </div> </li> </ul>
recipeForm.html
<h2>Edit Recipe</h2> <form name="recipeForm" ng-submit="save()" class="form-horizontal"> <div class="control-group"> <label class="control-label" for="title">Title:</label> <div class="controls"> <input ng-model="recipe.title" class="input-xlarge" id="title" focus> </div> </div> <div class="control-group"> <label class="control-label" for="description">Description:</label> <div class="controls"> <textarea ng-model="recipe.description" class="input-xlarge" id="description"></textarea> </div> </div> <div class="control-group"> <label class="control-label" for="ingredients">Ingredients:</label> <div class="controls"> <ul id="ingredients" class="unstyled" ng-controller="IngredientsCtrl"> <li ng-repeat="ingredient in recipe.ingredients"> <input ng-model="ingredient.amount" class="input-mini"> <input ng-model="ingredient.amountUnits" class="input-small"> <input ng-model="ingredient.ingredientName"> <button type="button" class="btn btn-mini" ng-click="removeIngredient($index)"> <i class="icon-minus-sign"></i> Delete </button> </li> <button type="button" class="btn btn-mini" ng-click="addIngredient()"> <i class="icon-plus-sign"></i> Add </button> </ul> </div> </div> <div class="control-group"> <label class="control-label" for="instructions">Instructions:</label> <div class="controls"> <textarea ng-model="recipe.instructions" class="input-xxxlarge" id="instructions"></textarea> </div> </div> <div class="form-actions"> <button class="btn btn-primary">Save</button> <button type="button" ng-click="remove()" ng-show="!recipe.id" class="btn"> Delete </button> </div> </form>
viewRecipe.html
<h2>{{ recipe.title }}</h2> <div>{{ recipe.description }}</div> <h3>Ingredients</h3> <ul class="unstyled"> <li ng-repeat="ingredient in recipe.ingredients"> <span>{{ ingredient.amount }}</span> <span>{{ ingredient.amountUnits }}</span> <span>{{ ingredient.ingredientName }}</span> </li> </ul> <h3>Instructions</h3> <div>{{ recipe.instructions }}</div> <form ng-submit="edit()" class="form-horizontal"> <div class="form-actions"> <button class="btn btn-primary">Edit</button> </div> </form>
运行效果(由于没有编写后台,不少地方会报错甚至不能成功运行):
附:GitHub上下载的工程源代码和用SeaJS组织的工程源代码
相关推荐
**组件化AngularJS应用——Phonecat的现代JavaScript与Webpack实现** 在现代Web开发中,组件化已经成为构建可维护、可复用和可扩展应用程序的重要模式。AngularJS,一个由Google维护的JavaScript框架,以其强大的...
AngularJS是一个由谷歌维护的开源前端JavaScript框架,用于构建动态网页应用程序。它通过使用HTML作为模板语言,引入了数据绑定、依赖注入、多组件支持等特性,从而简化了前端开发。本文将通过一个简单示例程序来...
AngularJS应用ppt,AngularJS应用ppt,AngularJS应用ppt
angularjs-style-guide, 社区驱动的AngularJS应用程序开发最佳实践集 简介这个样式指南的目标是为一个AngularJS应用程序提供一套最佳实践和风格指南。 这些最佳做法是从以下位置收集的:AngularJS源代码我已经阅读的...
angular-autolayout, 基于约束的AngularJS应用程序布局 AngularJS的自动布局基于约束的AngularJS布局范例 AngularJS AngularJS inspired inspired inspired iOS iOS的inspired Auto 。HTML和CSS设计用来呈现
angular-debaser, 一个更好的测试AngularJS应用程序的方法 角 debaser 一个更好的测试AngularJS应用程序的方法。这个想法AngularJS及其依赖注入使得在测试中隔离代码变得非常容易。不幸的是,为这些服务编写存根可以...
AngularJS是一款由Google维护的前端JavaScript框架,常用于构建单页应用(SPA,Single Page Applications)。这个名为"bonanzooka"的管理页面模板是基于AngularJS开发的,旨在为后端管理员提供一个用户界面友好、...
本资源提供了2013年的"用AngularJS开发下一代Web应用"的中英双版本电子书,旨在帮助开发者深入了解和掌握AngularJS的核心概念和技术。 在AngularJS中,双向数据绑定是最显著的特点之一。它使得模型和视图之间的数据...
资源名称:使用AngularJS开发下一代WEB应用内容简介:用AngularJS开发下一代Web应用的作者是两位在Google负责AngularJS框架的工程师,他们将引领读者概览整个框架的核心特性,并构建一款可运行的AngularJS应用,内容...
AngularJS,是由Google维护的JavaScript框架,用于构建交互式的单页应用程序(SPA)。它通过提供数据绑定和依赖注入等核心特性,极大地简化了前端开发流程,使得开发者可以更专注于业务逻辑,而非DOM操作。本教程将...
AngularJS Eclipse 1.2.0 插件是专为开发者设计的一款强大的工具,它将AngularJS框架与Eclipse集成,极大地提升了开发AngularJS应用程序的效率。Eclipse是一款广泛使用的开源集成开发环境(IDE),而AngularJS则是一...
《AngularJS Web 应用开发食谱》是由Matt Frisbie编写的经典编程书籍,它提供了90多个实用的食谱来帮助开发者构建高性能的AngularJS应用,并实施最佳实践。这本书在Amazon上获得了5星的高评价,显示出其在开发者群体...
AngularJS是由Google开发的开源前端JavaScript框架,它被设计为创建动态网页应用提供一套丰富工具,尤其是单页应用(SPA)。AngularJS的出现,标志着Web应用开发步入了新的阶段,它通过引入了诸多创新概念和方法来...
AngularJS是一种流行的前端JavaScript框架,它允许开发者利用它的MVC(模型-视图-控制器)特性来构建复杂的、单页的web应用。AngularJS的代码风格指南是用来指导开发者如何编写一致、可维护、高效的代码的一套规则和...
AngularJS 是一款由Google维护的前端JavaScript框架,用于构建单页Web应用(SPA,Single Page Applications)。这个合集包含了三本书籍,分别是《AngularJS by Example》、《AngularJS Web Application Development ...
AngularJS是一款由谷歌开发的开源JavaScript框架,用于创建动态网页应用。它利用HTML作为模板语言,并通过浏览器端的JavaScript来实现,从而补充了HTML在构建应用方面的不足。AngularJS的一个核心创新是引入了数据...