我遇到一个问题,让ng-class在flipCard
指令的模板中工作。从技术上讲,它确实有效,如果我在控制器中立即设置属性,它将添加css类。
在我看来,子指令可能是获取控制器的独立副本而不是共享基本flipCard
指令的控制器。因此,当我调用flipCtrl.move
时,它调用flipCardOver
指令的控制器实例,因为在flipCtrl.move
函数中设置控制器上的属性不会更新基本父项flipped
属性虽然控制台记录它说它设置为true。
目标:flipCard
上的控制器与flipCardBack
,flipCardFront
,flipCardOver
,flipCardReset
共享在页面上允许多个flipCard
指令并且没有冲突。
我错过了什么?
angular.module('cardFlip', [])
.controller('flipCardController', ['$scope', '$element', '$timeout', '$window',
function($scope, $element, $timeout, $window) {
var vm = this;
vm.flipped = false;
vm.moved = false;
vm.originalTop = -1;
vm.originalLeft = -1;
vm.move = function(e) {
vm.flipped = true;
console.log(vm.flipped);
};
vm.reset = function() {
vm.flipped = false;
};
}
])
.directive('flipCard', function() {
return {
restrict: 'AE',
controller: 'flipCardController',
controllerAs: 'flipCtrl',
scope: true,
transclude: true,
// LOOK: this is the template that I am expecting to change
template: '<div class="container"><div class="panel" ng-class="{ flip: flipCtrl.flipped, slide: flipCtrl.moved }" ng-transclude></div></div>'
}
})
.directive('flipCardFront', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="front" ng-transclude></div>'
}
})
.directive('flipCardBack', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="back" ng-transclude></div>'
}
})
.directive('flipCardOver', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
// LOOK: this is the event I am expecting to call move that sets flipped to true
element.on('click', flipCtrl.move);
}
}
})
.directive('flipCardReset', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
element.on('click', flipCtrl.reset);
}
}
});
/* Styles go here */
[ng-click] {
cursor: pointer;
}
.panel .pad {
padding: 0 15px;
}
.panel.flip .action {
display: none;
}
.panel {
float: left;
width: 200px;
height: 200px;
margin: 20px;
position: relative;
font-size: .8em;
-webkit-perspective: 600px;
perspective: 600px;
}
/* -- make sure to declare a default for every property that you want animated -- */
/* -- general styles, including Y axis rotation -- */
.panel .front {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 900;
width: inherit;
height: inherit;
background: #6b7077;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .front {
z-index: 900;
-webkit-transform: rotateY(179deg);
transform: rotateY(179deg);
}
.panel.slide {
top: 15%;
left: 15%;
-webkit-transition: all 5s ease-in-out;
transition: all 5s ease-in-out;
}
.panel .back {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 800;
width: inherit;
height: inherit;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
-webkit-transform: rotateY(-179deg);
transform: rotateY(-179deg);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .back {
z-index: 1000;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
</head>
<body>
<div ng-app="cardFlip">
<div ui-view="main">
<flip-card>
<flip-card-front>
<div style="width:50px;height:50px;" flip-card-over="function(){return true;}">
FRONT1
</div>
</flip-card-front>
<flip-card-back>
<div style="width:100px;height:100px;" flip-card-reset="function(){return true;}">
BACK1
</div>
</flip-card-back>
</flip-card>
</div>
</div>
</body>
</html>
答案 0 :(得分:2)
起初我也很难过,但后来我意识到 - 你还没有告诉Angular使用scope.$evalAsync()
进行更改(比$apply()
或$digest()
更安全,以防万一已经是一个消化发生了)。这是因为您自己处理点击,而不是使用ng-click
(触发摘要,因此不会出现此问题)。
这是forked Plunkr,它有效。
angular.module('cardFlip', [])
.controller('flipCardController', ['$scope', '$element', '$timeout', '$window',
function($scope, $element, $timeout, $window) {
var vm = this;
vm.flipped = false;
vm.moved = false;
vm.originalTop = -1;
vm.originalLeft = -1;
vm.move = function(e) {
vm.flipped = true;
console.log(vm.flipped);
};
vm.reset = function() {
vm.flipped = false;
};
}
])
.directive('flipCard', function() {
return {
restrict: 'AE',
controller: 'flipCardController',
controllerAs: 'flipCtrl',
scope: true,
transclude: true,
// LOOK: this is the template that I am expecting to change
template: '<div class="container"><div class="panel" ng-class="{ flip: flipCtrl.flipped, slide: flipCtrl.moved }" ng-transclude></div></div>'
}
})
.directive('flipCardFront', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="front" ng-transclude></div>'
}
})
.directive('flipCardBack', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="back" ng-transclude></div>'
}
})
.directive('flipCardOver', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
// LOOK: this is the event I am expecting to call move that sets flipped to true
element.on('click', function () {
flipCtrl.move();
scope.$evalAsync(); // tell Angular we did something
});
}
}
})
.directive('flipCardReset', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
element.on('click', function () {
flipCtrl.reset();
scope.$evalAsync(); // tell Angular
});
}
}
});
&#13;
/* Styles go here */
[ng-click] {
cursor: pointer;
}
.panel .pad {
padding: 0 15px;
}
.panel.flip .action {
display: none;
}
.panel {
float: left;
width: 200px;
height: 200px;
margin: 20px;
position: relative;
font-size: .8em;
-webkit-perspective: 600px;
perspective: 600px;
}
/* -- make sure to declare a default for every property that you want animated -- */
/* -- general styles, including Y axis rotation -- */
.panel .front {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 900;
width: inherit;
height: inherit;
background: #6b7077;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .front {
z-index: 900;
-webkit-transform: rotateY(179deg);
transform: rotateY(179deg);
}
.panel.slide {
top: 15%;
left: 15%;
-webkit-transition: all 5s ease-in-out;
transition: all 5s ease-in-out;
}
.panel .back {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 800;
width: inherit;
height: inherit;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
-webkit-transform: rotateY(-179deg);
transform: rotateY(-179deg);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .back {
z-index: 1000;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
}
&#13;
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
</head>
<body>
<div ng-app="cardFlip">
<div ui-view="main">
<flip-card>
<flip-card-front>
<div style="width:50px;height:50px;" flip-card-over="function(){return true;}">
FRONT1
</div>
</flip-card-front>
<flip-card-back>
<div style="width:100px;height:100px;" flip-card-reset="function(){return true;}">
BACK1
</div>
</flip-card-back>
</flip-card>
</div>
</div>
</body>
</html>
&#13;