Open uniquejava opened 8 years ago
翻页的动画效果合集(酷毙了): https://github.com/codrops/PageTransitions
<div ng-repeat="p in vm.points" class="prg-box" ng-class="{'first': $first, 'last': vm.points.length>1 && $last}"
ng-style="{left: p.left}">
<div class="prg-text" ng-bind-html="p.text"></div>
<div class="bottomArrow"></div>
</div>
data可以是string或是js object
$http.get(url, config)
$http.post(url, data, config)
$http.put(url, data, config)
$http.delete(url, config)
$http.head()
$http(config)
config
对象
{
// 所用的HTTP方法
method: 'POST',
// 请求的目标URL
url: '',
// URL的参数
params: {key1: "value1"},
// 额外的请求头
headers: {},
// XHR请求终止前的超时时间(单位是ms)
timeout: 3000,
// XHR GET请求的缓存开关
cache: false,
// 在与后端交换数据前或交换后, 对数据进行处理的数据变换函数
transformRequest: function(){},
transformResponse: function(){}
}
处理回调: $http(config).then(successCb, errorCb)或$http(config).success(cb).error(cb), 其中cb
包含4个参数.
function cb(
data, // 实际的响应数据
status, // 响应的HTTP状态
headers, // 访问HTTP响应头信息的函数
config // 请求触发时提供的配置对象
){}
设想我们要重试失败的请求, 我们可以定义一个拦截器用于检查响应状态码, 并在探测到HTTP Service Unavailable(503,服务无效)状态码时重试此请求, 代码大略如下:
解释见书P105页
var xx = angular.module('xx', []);
xx.config(function($httpProvider){
$httpProvider.responseInterceptors.push('retryInterceptor');
})
.factory('retryInterceptor', function($injector, $q){
return function(responsePromise){
return responsePromise.then(null, function(errResponse){
if(errResponse.status === 503){
return $injector.get('$http')(errResponse.config);
} else {
return $q.reject(errResponse);
}
}
}
})
详见书P84页
// 基本用法
function getXx() {
var d = $q.defer()
d.resolve(...);
d.reject(new Error(...))
return d.promise;
}
getXx().then(successCb, errorCb);
// 链式处理promise
function slice(pizza){
return 'sliced ' + pizza;
}
getXx().then(slice).then(successCb, errorCb)
// 聚合多个promise
$q.all([p1, p2]).then(cb1, cb2)
// 包装任意对象为promise
$q.when('hello world')
https://stackoverflow.com/questions/21269007/interceptor-not-working/21269115#21269115
https://github.com/Foxandxss/angular-toastr
bower install angular-toastr --save
angular.module('app', ['ngAnimate', 'toastr'])
最简单的用法
app.controller('foo', function($scope, toastr) {
toastr.success('Hello world!', 'Toastr fun!');
});
解决办法: There are two simple ways to solve that kind of circular dependency problem
decouple the services by using events: when an error is detected in the interceptor, broadcast an event (with the error information) on the root scope. In the toastr service (or in a service that uses toastr), listen on these events on the root scope and display them.
instead of injecting toastr in the interceptor, inject the $injector service. And when you need a toastr instance, call $injector.get('toastr')
.
我最终选择了第二种.
有两种办法, 一种是直接在interceptor中使用$injector.get('toastr').error('message here')
这是我实际选择的方式.
另一种是在interceptor中使用$rootScope.$broadcast('message', ..), 然后在config中$rootScope.on('message', ....);
: 见: http://thoughtdelimited.org/thoughts/post.cfm/angular-material-design-mdtoast-and-httpinterceptors
综合以上, 我定义了如下InterceptorService.js
(function () {
'use strict';
angular.module('myapp')
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('errorInterceptor');
}])
.config(['toastrConfig', function (toastrConfig) {
angular.extend(toastrConfig, {
autoDismiss: true,
containerId: 'toast-container',
maxOpened: 0,
newestOnTop: true,
positionClass: 'toast-top-right',
preventDuplicates: false,
preventOpenDuplicates: false,
target: 'body'
});
}])
.factory('errorInterceptor', errorInterceptor);
/** @ngInject */
function errorInterceptor($q, $rootScope, $injector) {
return {
request: function (config) {
return config || $q.when(config);
},
requestError: function (request) {
return $q.reject(request);
},
response: function (response) {
return response || $q.when(response);
},
responseError: function (response) {
var status = response.status;
var msg;
if (status === -1) {
msg = 'Backend service is not available.';
} else if (status === 401) {
msg = status + ': You are not authorized, please login first.';
} else if (status === 403) {
msg = status + ': You have no permission.';
} else if (status === 404) {
msg = status + ': Requested resource is not available.';
} else if (status >= 500) {
msg = status + ': Internal Server Error.';
}
$injector.get('toastr').error(msg);
return $q.reject(response);
}
};
}
})();
http://stackoverflow.com/questions/18202106/ng-options-with-simple-array-init 最终的代码
<div class="form-group">
<label for="reg-loc-province">省份/直辖市</label>
<select class="form-control" id="reg-loc-province"
ng-model="user.address.province" ng-options="b for b in provs track by b">
</select>
</div>
http://stackoverflow.com/questions/14968297/use-underscore-inside-angular-controllers
When you include Underscore, it attaches itself to the window object, and so is available globally.
So you can use it from Angular code as-is.
You can also wrap it up in a service or a factory, if you'd like it to be injected:
var underscore = angular.module('underscore', []);
underscore.factory('_', ['$window', function($window) {
return $window._; // assumes underscore has already been loaded on the page
}]);
And then you can ask for the _ in your app's module:
// Declare it as a dependency of your module
var app = angular.module('app', ['underscore']);
// And then inject it where you need it
app.controller('Ctrl', function($scope, _) {
// do stuff
});
既然_已经注入到了window对象, 为什么还要像上面这样定义成angularjs的service呢?
答案: its necessary when you add 'use strict' to your file. Since underscore/lodash isn't defined it will throw ReferenceError: is not defined... you have to inject it, or use window.
http://stackoverflow.com/questions/17922557/angularjs-how-to-check-for-changes-in-file-input-fields
这个问题好多人收藏!!!!
var UserSchema = new Schema({
username: {type: String},
svcs: [{
_id: {type: mongoose.Schema.ObjectId, default: new mongoose.Types.ObjectId()},
name: {type: String}, // 名称
descr: {type: String}, // 描述
image: {type: String} // 图片
}]
});
在controller中像这样构造值:
svc = {
_id: req.body._id || new ObjectId,
name: req.body.name,
descr: req.body.descr,
image: req.body.image,
};
在service中像这样做增删改..
if (operation === 'add') {
X.update({'loginname': loginname}, {$push: {'svcs': svc}}, function (err) {
if(err) {
return callback(err);
} else {
X.findOne({'loginname': loginname}, 'svcs', function (err, svcs) {
callback(err, svcs);
});
}
});
} else if (operation === 'delete') {
X.update({'loginname': loginname}, {$pull: {'svcs': {_id: ObjectId(svc._id)}}}, callback);
} else if (operation === 'update') {
X.update({'loginname': loginname, 'svcs._id': ObjectId(svc._id)},
{
$set: {
'svcs.$.name': svc.name,
'svcs.$.descr': svc.descr,
'svcs.$.image': svc.image,
}
}, callback);
}
啊, 突然意识到在add的时候不用再做一次查询以获得新增对象_id的值, 因为_id在外部已经生成好了.
Configuration block – This block is executed during the provider registration and configuration phase. Only providers and constants can be injected into configuration blocks. This block is used to inject module wise configuration settings to prevent accidental instantiation of services before they have been fully configured. This block is created using config() method.
Run block – This block is executed after the configuration block. It is used to inject instances and constants. This block is created using run() method. This method is like as main method in C or C++. The run block is a great place to put event handlers that need to be executed at the root level for the application. For example, authentication handlers.
示例: http://www.angularjshub.com/examples/modules/configurationrunphases/
http://stackoverflow.com/questions/15666048/angularjs-service-vs-provider-vs-factory
The main role of the top-level controller in the SportsStore application is to define the data that will be used inthe different views that the application will display. As you will see—and as I describe in detail in Chapter 13—an AngularJS can have multiple controllers arranged in a hierarchy. Controllers arranged in this way can inherit data andlogic from controllers above them, and by defining the data in the top-level controller, I can make it easily available to the controllers that I will be defining later.
I need to make sure the inline script element (the one that defines the module) appears before the one that imports the file (which extends the module).
I will be using the sportsStoreCtrl controller to support the entire application, so I have applied it to the body element so that the view it supports is the entire set of content elements. This will start to make more sense when I begin to add other controllers to support specific features.
There are no hard-and-fast rules about when you should add a component to an existing module or create a new one. I tend to create modules when I am defining functionality that I expect to reuse in a different application later. Custom filters tend to be reusable because data formatting is something that almost all AngularJS applications require and most developers end up with a utility belt of common formats they require.
Changes that a filter makes to the data affect only the content displayed to the user and do not modify the original data in the scope.
Notice that I am able to define the script element for the customFilters.js file after the one that creates the sportsStore module and declares a dependency on the customFilters module. This is because AngularJS loads all of the modules before using them to resolve dependencies. The effect can be confusing: The order of the script elements is important when you are extending a module (because the module must already have been defined) but not when defining a new module or declaring a dependency on one
You might be wondering why the view can’t access the constant values directly, instead of requiring everything to be explicitly exposed via the scope. The answer is that AngularJS tries to prevent tightly coupled components, which I described in Chapter 3. If views could access services and constant values directly, then it would be easy to end up with endless couplings and dependencies that are hard to test and hard to maintain.
It may not be obvious when testing the changes, but obtaining the data via Ajax highlights one of the most important aspects of AngularJS development, which is the dynamic nature of scopes. When the application first starts, the HTML content is generated and displayed to the user even though there is no product information available. At some point after the content has been rendered, the data will arrive from the server and be assigned to the data.products variable in the scope. When this happens, AngularJS updates all of the bindings and the output from behaviors that depend on the product data, ensuring that the new data is propagated throughout the application. In essence, AngularJS scopes are live data stores, which respond and propagate changes. You will see countless examples of this propagation of changes throughout the book.
There are three benefits to using partial views. The first is to break up the application into manageable chunks, as I have done here. The second is to create fragments of HTML that can be used repeatedly in an application. The third is to make it easier to show different areas of functionality to the user as they use the application—I’ll return to this benefit in the “Defining URL Routes” section later in the chapter.
When using the ng-include directive, I specified the name of the file as a literal value in single quotes. If I had not done this, then the directive would have looked for a scope property to get the name of the file.
http://stackoverflow.com/questions/16094940/what-is-the-lifecycle-of-an-angularjs-controller
配合ui-router, 当切换state时, controller连同$scope会一起销毁. 可以在$scope.on('destroy', callback)中清理$scope的资源. (比如在外部对象上注册的subscriber).
一共有7种原因: 见 https://stackoverflow.com/questions/15535336/combating-angularjs-executing-controller-twice?rq=1
见: https://stackoverflow.com/questions/23813599/set-page-title-using-ui-router
There is a another way of doing this by combining most of the answers here already. I know this is already answered but I wanted to show the way I dynamically change page titles with ui-router.
If you take a look at ui-router sample app, they use the angular .run block to add the $state variable to $rootScope.
// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.
// For example, <li ng-class="{ active: $state.includes('contacts.list') }">
// will set the <li> to active whenever 'contacts.list' or one of its
// decendents is active.
.run([ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
With this defined you can then easily dynamically update your page title with what you have posted but modified to use the defined state:
Setup the state the same way:
.state('home', {
url: '/home',
templateUrl : 'views/home.html',
data : { pageTitle: 'Home' }
})
But edit the html a bit...
<title ng-bind="$state.current.data.pageTitle"></title>
I can't say this is any better than the answers before... but was easier for me to understand and implement. Hope this helps someone!
books
Pro AngularJS.
💯 Angular源码解析
http://www.html-js.com/article/column/693
https://scotch.io/tutorials/angular-routing-using-ui-router
👍 ngRoutes vs ui-router详解 http://www.cnblogs.com/lovesueee/p/4442509.html
👍 scopes and digest http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html
👍AngularJS性能调优
https://github.com/xufei/blog/issues/23
angular快速上手