我在这里要做的是创建一个指令,允许我设置仅适用于我正在渲染的html标记内的临时变量。用例是这样的:
<div class="input-group" ng-local="opened = false" ng-blur="opened = false;">
<input type="text" class="form-control" uib-datepicker-popup="longDate" ng-model="start" is-open="opened" ng-focus="opened = true;" />
<span class="input-group-btn">
<button type="button" ng-click="opened = true;" class="fa fa-calendar" ></button>
</span>
</div>
这里的想法是ng-local指令创建变量opened
并将该变量设置为初始值false
。指令内的所有内容都是一个被转换的模板。这里的好处是我可以在页面上使用多个日期选择器,所有使用相同变量opened
的人都不必拥有一堆不同的变量,这些变量都位于控制器中的范围内,该控制器仅用作临时变量对于div内的内容。但是,由于这将以多种不同的方式使用,我不想为每个用例制定不同的指令。
我对此的第一次尝试非常顺利。但是,我遇到了一个问题,即从datepicker无法正确访问父作用域变量start
。我对$ transclude功能不太熟悉,所以我希望有人可以指出我正确的方向。这是我目前写的指令:
(function () {
angular.module('myApp').directive('ngLocal', [function () {
return {
restrict: 'A',
transclude: 'element',
replace: false,
scope: {
ngLocal: '@'
},
link: function ngLocalLink(directiveScope, element, attrs, ctrl, $transclude) {
$transclude(directiveScope, function ngLocalTransclude(clone, scope) {
element.empty();
element.replaceWith(clone);
scope.$eval(directiveScope.ngLocal);
});
}
};
}]);
})();
提前致谢!
修改
这是一个plunkr链接
答案 0 :(得分:0)
请尝试使用$parent.localDate
。
<div class="input-group" ng-local="localOpen = false">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen" ng-model="$parent.localDate" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
</span>
</div>
如果您不想使用$ parent,可以使用隔离范围,并设置您要使用的变量:
<div class="input-group" ng-local="localOpen = false" date="localDate">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen" ng-model="date" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
</span>
</div>
angular.module('myApp').directive('ngLocal', [function () {
return {
restrict: 'A',
transclude: 'element',
replace: false,
scope: {
ngLocal: '@',
date: '='
},
link: function ngLocalLink(directiveScope, element, attrs, ctrl, $transclude) {
$transclude(directiveScope, function ngLocalTransclude(clone, scope) {
element.empty();
element.replaceWith(clone);
scope.$eval(directiveScope.ngLocal);
});
}
};
}]);
这是分叉的plunker:https://plnkr.co/edit/4zrNzbSc5IwqqbE2ISE1?p=preview
答案 1 :(得分:0)
您的指令中不需要转换,只需创建child or isolate scope。
样品
angular.module('myApp', ['ngAnimate', 'ui.bootstrap']);
// CONTROLLER
angular.module('myApp').controller('myController', function($scope) {
$scope.dates = {
workingDate : new Date(),
brokenDate1 : new Date(),
brokenDate2 : new Date(),
localDate : new Date(),
}
});
// DIRECTIVE
angular.module('myApp').directive('ngLocal', [
function() {
return {
restrict: 'A',
replace: false,
scope: true //directive have own scope
};
}
]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.1.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<div ng-app="myApp">
<div ng-controller="myController">
<h4>This one works</h4>
<div class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="workingOpen" ng-model="dates.workingDate" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="workingOpen = true" >OPEN</button>
</span>
</div>
<br/>
<br/>
<br/>
<h4>This is the problem I'm trying to solve</h4>
<h4>Both datepickers use "brokenOpen" so they both open whenever either is clicked</h4>
<div style="width: 40%; display: inline-block;" ng-local>
<div class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="brokenOpen" ng-model="dates.brokenDate1" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="brokenOpen = true" >OPEN</button>
</span>
</div>
</div>
<div style="width: 40%; display: inline-block;" ng-local>
<div class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="brokenOpen" ng-model="dates.brokenDate2" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="brokenOpen = true" >OPEN</button>
</span>
</div>
</div>
<br/>
<br/>
<br/>
<h4>This is using my directive</h4>
<h4>The date does not update correctly to the parent scope</h4>
<div class="input-group" ng-local="localOpen = false">
<input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen" ng-model="dates.localDate" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
</span>
</div>
<label>See how the date is not updating: {{dates.localDate}}</label>
</div>
</div>
&#13;
答案 2 :(得分:0)
尝试嵌套指令。 outer指令封装了你想要共享的数据,而inner指令则从外部提供的函数中获取数据。
链接到演示: https://plnkr.co/edit/4n6kf40ZMf7lRCad5ofe?p=preview
代码:
angular.module('myapp', [])
.directive('outer', function () {
return {
restrict: 'E',
transclude: true,
scope: {
value: '='
},
template: function(element, attrs) {
return '<div>outer! value = {{value}}<div ng-transclude></div></div>';
},
controller: function($scope) {
this.getValue = function() {
return $scope.value;
}
}
}
})
.directive('inner', function () {
return {
restrict: 'E',
template: function(element, attrs) {
return '<div>inner! value = {{value}}</div>';
},
require: '^outer',
link: function (scope, element, attrs, parentCtrl) {
scope.$watch(
function() {
return parentCtrl.getValue();
}, function(oldValue, newValue) {
scope.value = parentCtrl.getValue();
}
);
}
}
});
答案 3 :(得分:0)
我希望获得与
ng-repeat
类似的功能,您不必通过transcluded元素中的父作用域来解决所有问题。
ng-repeat
没有使用隔离范围。它使用继承范围。
有关指令范围的更多信息,请参阅AngularJS $compile Service API Reference -- scope。
此自定义指令多次转换其内容,每次都创建一个新的继承范围。通过阅读repeat
属性确定重复次数。
angular.module('myApp').directive('repeat', function () {
return{
scope: false,
transclude: 'element',
link : function(scope, element, attrs, ctrl, transcludeFn){
var parent = element.parent();
var repeatNum = attrs.repeat;
for(var i = 1;i<= repeatNum;++i){
var childScope = scope.$new();
childScope.$index = i;
transcludeFn(childScope, function (clone) {
parent.append(clone);
})
}
}
}
})