angularjs显示html文本

Angularjs中输出变量使用花括号或者ng-bind,但是如果变量中有html代码的话,angularjs为了xss安全,默认是不解析html,直接原样显示html代码。
如果需要显示解析后的html代码,需要使用angular-sanitize模块。

angular-sanitize一般会附带在angularjs中,如果没有附带,请前往官网下载对应版本的angular-sanitize模块。

模块代码

1
var demo = angular.module('demo',['ng-sanitize']);

angularjs icheck

angularjs上传指令

chrome hosts插件

移动端滚动加载问题

angularjs ng-options第一个选项为空的解决方案

angularjs的ng-options渲染到页面上的时候结构大致是这样的。

1
2
3
4
<select>
<option value=""></option>
<option value="1">北京</option>
</select>

这样会导致select第一行为空,用户体验很差。所以改造后的代码如下

angularjs 用户认证解决方案

作为一个全栈ajax的mvvm框架,angularjs可谓如火如荼,可真正做到全栈ajax,首要面对的问题就是用户身份验证。
本文的身份验证不采用cookie,而采用基于http Authorize 请求头的方式验证用户,此方式能做到永远只有一个用户同时在线(服务端同一时间只会接受一个合法的token请求,其他的请求返回401)。

Service

1
2
3
4
5
6
7
8
9
10
11
12
app.factory('Authorize', function() {
return {
uid: '',
token: '',
logout: function() {
this.uid = '';
this.token = '';
localStorage.removeItem('authorize.uid');
localStorage.removeItem('authorize.token');
}
}
});

由于service是单例的。保存在service很合适,再看登录检测。

angularjs集成requirejs

angularjs自带的模块话机制对于业务逻辑的组织确实起到了规范化的作用,但是对于大型web项目,弊端也出来了,一次性加载所有的资源会导致进入应用的时间变长,而实际上,首页需要加载的并不多,所以,本文将介绍如何使用requireJs与angularJs集成。

依赖

  • jquery(非必须)

angularjs指令实现radioGroup

angularjs的指令系统其实也是很强大的东西,扩展了HTML的表现力。本文讲的是如何用angularjs指令实现radioGroup,自带的radio只能控制ngModel的两种状态: true/false。

指令代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module.directive('radio', [function() {
return {
transclude: true,
replace: true,
template: '<div class="ui ui-radio"><span class="radio-item"></span><span ng-transclude="" class="common-color"></span></div>',
require: 'ngModel',
link: function(scope, ele, attrs, ctrl) {
ctrl.$render = function() {
if(ctrl.$viewValue == attrs.value) {
//jqLite不支持siblings方法,如果此段代码无效,请使用zepto实现
ele.parent().children().removeClass("active");
ele.addClass("active");
}
};
ele.bind("click", function() {
ctrl.$setViewValue(attrs.value);
ele.addClass("active");
var childrens = ele[0].parentNode.children;
for(var i = 0; i < childrens.length; i++) {
if(childrens[i] != ele[0]) {
angular.element(childrens[i]).removeClass("active");
}
}
});
}
};
}]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.ui {
&-radio {
&.active {
.radio-item:after {
display: block;
width: 19px;
height: 19px;
content: ' ';
position: absolute;
border-radius: 50%;
left: (35px-19)/2;
top: (35px-19)/2;
background: #d14db7;
}
}
.radio-item {
width: 35px;
height: 35px;
border-radius: 50%;
position: relative;
background: white;
display: inline-block;
vertical-align: middle;
margin: 0;
}
span {
margin-left: 12px;
}
}
}

带进度条的angularjs上传指令

项目地址

https://git.coding.net/xialei/xl-angular-upload.git

效果图

图1
图2

指令代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
angular.module('xl-angular-upload', [])
.directive('angularUpload', [function () {
return {
restrict: 'E',
require: 'ngModel',
template: '<div class="xl-angular-upload">\n <!--upload button-->\n <button class="xl-btn btn-primary">上传\n <input type="file"/>\n </button>\n <!--upload queue-->\n <div class="queue">\n <div class="item" ng-repeat="item in queue">\n <div class="info">\n <div class="no">{{$index+1}}</div>\n <div class="name">{{item.name}}</div>\n <div class="size">{{(item.size/1024).toFixed(2)}}KB</div>\n </div>\n <div class="process-bar">\n <div class="process" style="width:{{item.process}}%"></div>\n </div>\n </div>\n </div>\n</div>',
replace: true,
link: function (scope, ele, attrs, ctrl) {
//必要属性检测
if (!attrs.action) {
throw new Error('请设置上传action');
}
//初始化
scope.queue = [];
var file = angular.element(document.querySelector('.xl-angular-upload>.xl-btn>input[type="file"]'));
var files = [];
attrs.accept && file.attr('accept', attrs.accept);
attrs.multiple && file.attr('multiple', attrs.multiple);
file.bind("change", function (e) {
scope.$apply(function () {
scope.queue = [];
for (var i in e.target.files) {
if (/^\d+$/.test(i)) {
e.target.files[i].process = 0;
scope.queue.push(e.target.files[i]);
}
}
});
//准备上传
scope.queue.forEach(function (item) {
var data = new FormData;
data.append(attrs.name || 'file', item);
var xhr = new XMLHttpRequest();
xhr.open('POST', attrs.action, true);
//事件监听
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
//上传完成了
var resp = JSON.parse(xhr.responseText);
if (resp.error) {
throw new Error(resp.error);
} else {
files.push(resp);
ctrl.$setViewValue(files);
}
}
};
xhr.onerror = function (error) {
throw new Error(error);
};
xhr.upload && (xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
scope.$apply(function () {
item.process = parseInt((e.loaded / e.total) * 100);
});
}
});
xhr.send(data);
});
});
}
}
}]);
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×