我正在构建一个自定义指令,允许将glyphicon用作指示符(颜色),通知(工具提示),简单操作(单击)以及在模态(双击)中自定义操作的功能。
以下是plunker我的进展。
首次加载时颜色是正确的 - 如果值= 0则为灰色,值为1时为绿色,值为2时为红色。单击也正确 - 单击0变为1,单击1变为2和a 2单击变为1。
但是,颜色对点击的响应不正确。第一次点击似乎被忽略,因为颜色保持不变,第二次点击确实触发了颜色变化,但现在1 =红色,2 =绿色(向后)。
任何人都可以看到我做错了会导致配色方案失败吗?
这是来自plunker的代码 -
app.js
(function() {
angular.module('app', ['ui.bootstrap'])
.directive('sglclick', SingleClickDirective)
.directive('loanProgressIcon', LoanProgressIconDirective)
.controller('MainController', MainController);
function SingleClickDirective($parse) {
return {
restrict: 'A',
link: function(scope, element, attr) {
var fn = $parse(attr['sglclick']);
var delay = 300,
clicks = 0,
timer = null;
element.on('click', function(event) {
clicks++; //count clicks
if (clicks === 1) {
timer = setTimeout(function() {
fn(scope, {
$event: event
});
clicks = 0; //after action performed, reset counter
}, delay);
} else {
clearTimeout(timer); //prevent single-click action
clicks = 0; //after action performed, reset counter
}
});
}
};
}
function LoanProgressIconDirective($compile) {
var progressMarkers = [{
'id': 1,
'cat': 'its_list',
'glyph': 'list-alt',
'tip': 'ITS List Verfified'
}, {
'id': 2,
'cat': 'fsa_compliant',
'glyph': 'home',
'tip': 'FSA Eligibility'
}, {
'id': 3,
'cat': 'has_liens',
'glyph': 'star',
'tip': 'Prior Lien Verfied'
}, {
'id': 4,
'cat': 'valid_leases',
'glyph': 'leaf',
'tip': 'Leases Valid'
}];
var statusColors = [
{ val: 0, color: '#CCC', class: 'pending'},
{ val: 1, color: '#006837', class: 'completed'},
{ val: 2, color: '#900', class: 'overdue'}
];
return {
restrict: 'A',
require : 'ngModel',
link: linker,
templateUrl: 'loanProgress.html',
scope: {
cat: '@',
ngModel: '='
}
};
function linker(scope, element, attrs, ctrl) {
scope.loan = {
id: progressMarkers[scope.cat]['id'],
glyphicon: progressMarkers[scope.cat]['glyph'],
tooltip: progressMarkers[scope.cat]['tip']
};
var styleChange = function () {
scope.loan.style = statusColors[scope.ngModel]['color'];
};
styleChange();
var setter = ctrl.$setViewValue;
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
styleChange();
};
scope.progClicked = function() {
if(parseInt(scope.ngModel) === 0){
ctrl.$setViewValue(1);
} else if(parseInt(scope.ngModel) === 1){
ctrl.$setViewValue(2);
} else if(parseInt(scope.ngModel) === 2){
ctrl.$setViewValue(1);
}
};
scope.progDblClicked = function() {
alert('Icon ' + scope.ngModel + ' was double clicked.');
};
}
}
function MainController($scope) {
$scope.loan = {
its_list: 1,
fsa_compliant: 2,
has_liens: 1,
valid_leases: 0
};
}
})();
的index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="bootstrap@3.0.2" data-semver="3.0.2" src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>
<script data-require="angular.js@1.2.4" data-semver="1.2.4" src="http://code.angularjs.org/1.2.4/angular.js"></script>
<script data-require="ui-bootstrap@*" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<link data-require="bootstrap-css@3.0.2" data-semver="3.0.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<script src="app.js"></script>
</head>
<body ng-controller="MainController">
<div class="container">
<div class="row">
<div class="col-xs-12">
<table class="table table-striped">
<thead>
<tr>
<th colspan="4" class="text-left">LOAN PROGRESS ICONS</th>
</tr>
</thead>
<tbody>
<tr>
<th>ITS</th>
<th>FSA</th>
<th>LIEN</th>
<th>LEASES</th>
</tr>
<tr>
<td>
<span loan-progress-icon cat="0" ng-model="loan.its_list"></span>
</td>
<td>
<span loan-progress-icon cat="1" ng-model="loan.fsa_compliant"></span>
</td>
<td>
<span loan-progress-icon cat="2" ng-model="loan.has_liens"></span>
</td>
<td>
<span loan-progress-icon cat="3" ng-model="loan.valid_leases"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<p>{{loan | json}}</p>
</div>
</div>
</div>
</body>
</html>
指令模板:
<span sglclick="progClicked()" ng-dblclick="progDblClicked()" class="glyphicon glyphicon-{{loan.glyphicon}}" tooltip="{{loan.tooltip}}" style="font-size:18px;color:{{loan.style}};cursor:pointer;"></span>
和app.css
th, td{
text-align:center;
}
.row{
margin: 15px 0;
}
.completed{
color: #006837;
}
.pending{
color: #CCCCCC;
}
.overdue{
color: #990000;
}
提前致谢!
答案 0 :(得分:1)
第一个问题是由于on
是jqLite / jQuery方法并且不为您触发摘要循环。这意味着不会更新UI以反映模型的更改。
您需要在调用$apply
或使用$timeout
代替setTimeout
时包装影响模型的代码。
使用$apply
:
timer = setTimeout(function() {
scope.$apply(fn(scope, {
$event: event
}));
clicks = 0;
}, delay);
使用$timeout
:
element.on('click', function(event) {
clicks++; //count clicks
if (clicks === 1) {
timer = $timeout(function() {
fn(scope, {
$event: event
});
clicks = 0;
}, delay);
} else {
$timeout.cancel(timer); //prevent single-click action
clicks = 0; //after action performed, reset counter
}
});
第二个问题是以下代码:
var setter = ctrl.$setViewValue;
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
styleChange();
};
在调用$setViewValue
之后,内部ngModelWatch将不会检测到更改并更新指令中的ngModel,直到稍后运行摘要循环时。目前styleChange
会在此之前运行。
要在摘要循环结束后运行styleChange
,您可以使用$timeout
:
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
$timeout(styleChange);
};