AngularJS:自定义指令未正确计算数据要求
我正在构建一个自定义指令,允许glyphicon用作指示器(颜色)、通知(工具提示)、简单操作(单击)和模式中自定义操作的功能(双击) 这是我进步的一部分 第一次加载时,颜色是正确的——如果值为0,则为灰色,值为1时为绿色,值为2时为红色。单击也是正确的--单击的0变为1,单击的1变为2,单击的2变为1 但是,颜色对单击没有正确响应。第一次单击似乎被忽略,因为颜色保持不变,第二次单击确实会触发颜色更改,但现在1=红色,2=绿色(向后) 有人能看出我做错了什么会导致配色方案失败吗 这是plunker的代码-- app.jsAngularJS:自定义指令未正确计算数据要求,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我正在构建一个自定义指令,允许glyphicon用作指示器(颜色)、通知(工具提示)、简单操作(单击)和模式中自定义操作的功能(双击) 这是我进步的一部分 第一次加载时,颜色是正确的——如果值为0,则为灰色,值为1时为绿色,值为2时为红色。单击也是正确的--单击的0变为1,单击的1变为2,单击的2变为1 但是,颜色对单击没有正确响应。第一次单击似乎被忽略,因为颜色保持不变,第二次单击确实会触发颜色更改,但现在1=红色,2=绿色(向后) 有人能看出我做错了什么会导致配色方案失败吗 这是plunke
(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>
提前谢谢 第一个问题是由于上的
是一个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
}
});
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
$timeout(styleChange);
};
第二个问题是以下代码:
var setter = ctrl.$setViewValue;
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
styleChange();
};
调用$setViewValue
后,内部ngModelWatch将不会检测到更改并更新指令中的ngModel,直到稍后运行摘要循环。当前styleChange
在这种情况发生之前运行
要在摘要循环完成后运行styleChange
,可以使用$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
}
});
ctrl.$setViewValue = function() {
setter.apply(this, arguments);
$timeout(styleChange);
};
演示:非常好的解释。。。我希望你写的教程和课程的角度,我正试图学习这一点!很高兴我能帮上忙,谢谢你的客气话:)