这是一个柱塞-我希望将“替换”替换为“替换”。
我的问题如下。我有两个指令myTabs和myPane在myTabs的link
函数中,我向其隔离范围添加了一个方法setValue
。现在,我希望myPane能够设置值,因此我setValue
在myTabs的控制器中添加了一个方法,该方法基本上调用了示波器的方法。但是,由于控制器功能是在链接功能之前运行的,因此无法访问范围的方法。
有关完整的代码,请参阅Plunker,但以下是相关部分:
指令:
angular.module('docsTabsExample', [])
.directive('myTabs', function() {
return {
transclude: true,
scope: {},
controller: function($scope) {
this.setValue = $scope.setValue;
},
link: function(scope, element, attrs){
scope.value = 'To be replaced';
scope.setValue = function(value){
scope.value = value;
};
},
templateUrl: 'my-tabs.html'
};
})
.directive('myPane', function() {
return {
require: '^myTabs',
transclude: true,
scope: {
},
link: function(scope, element, attrs, tabsCtrl) {
tabsCtrl.setValue('Replacement');
}
};
});
HTML:
<body ng-app="docsTabsExample">
<my-tabs>
<my-pane>
One pane
</my-pane>
<my-pane title="World">
Another pane
</my-pane>
</my-tabs>
</body>
当运行,在控制台中可以看到Error: tabsCtrl.setValue is not a function
。
现在,只是为了确保我没有朝错误的方向前进,我应该描述我的实际问题。我正在写一个指令,require
s ^ ngModel,并具有嵌套指令。由于我只能在链接函数中访问ngModel的控制器,因此只能将setValue()方法添加到该函数的作用域中,但是我需要控制器将API暴露给嵌套指令,这就是我要这样做的原因this.setValue = $scope.setValue;
。
您确实只需要让指令控制器管理对$ scope的访问。
创建控制器时,它将具有与指令相同的作用域,因此您可以重新编写控制器代码,使其看起来像这样:
controller: function($scope) {
//Snip...
this.setValue = function(value){
$scope.value = value;
};
}
将逻辑转移到控制器后,您可以安全地从指令中删除范围函数。但是,您需要解决一个操作顺序问题。
默认情况下,alink: function(){}
是一个Post Linking函数,它将在链接所有子指令之后执行。您可以通过将逻辑移到“预链接”功能来解决此问题,因为该功能在链接子指令之前执行。
link: {
pre: function(scope, element, attrs){
scope.value = 'To be replaced';
//No need for function here
}
}
现在,您的嵌套指令可以简单地在控制器上执行方法,这将依次在范围上设置适当的值。那里什么都不需要改变。
这是具有这些更改的Plunker:http ://plnkr.co/edit/ERf24t93rm1pmr8avyV1?p=preview
好的,这是一个完整的示例,展示了如何ngModel
在子指令中使用它来影响实际的绑定模型。您可以看到<input>
绑定progressValue
和实际自定义控件中的更改都已更新。
如果您想自己玩这个游戏,这里有一个Plunker:http ://plnkr.co/edit/zdzm0l4THlCDTvdP4ne3?p=preview
(function() {
var template = '<div>' +
'<div ng-transclude></div>' +
'<div class="progress">' +
'<div class="progress-bar progress-bar-success progress-bar-striped"' +
' role="progressbar" aria-valuenow="0"' +
' aria-valuemin="0" aria-valuemax="100">' +
'<span></span>' +
'</div>' +
'</div>' +
'</div>';
function ParentWithModelDirective() {
return {
restrict: 'E',
require: 'ngModel',
template: template,
transclude: true,
replace: true,
scope: {},
link: {
pre: function(scope, elem, attrs, ngModel) {
var progressBar = elem.find('div').find('div'),
label = progressBar.find('span');
ngModel.$parsers.push(function(viewValue) {
var numValue = 0;
if (angular.isString(viewValue)) {
viewValue = viewValue.replace('%', '');
}
numValue = parseInt(viewValue);
return isNaN(numValue) ? 0 : numValue;
});
ngModel.$formatters.push(function(value) {
return ngModel.$isEmpty(value) ? 'N/A' : value.toString() + '%';
});
ngModel.$render = function() {
progressBar.css('width', ngModel.$viewValue);
progressBar.attr('aria-valuenow',
ngModel.$isEmpty(ngModel.$modelValue) ?
0 :
ngModel.$modelValue);
label.text(ngModel.$viewValue);
};
}
}
};
}
function ChildOfParentDirective() {
return {
restrict: 'E',
require: '^ngModel',
template: "<button type='button' class='btn btn-success'>Complete</button>",
scope: {},
link: function(scope, elem, attrs, ngModel) {
function listener() {
ngModel.$setViewValue('100%', 'click');
ngModel.$render();
}
elem.on('click', listener);
}
};
}
function AnotherChildOfParentDirective() {
return {
restrict: 'E',
require: '^ngModel',
template: "<button type='button' class='btn btn-warning'>Reset</button>",
scope: {},
link: function(scope, elem, attrs, ngModel) {
function listener() {
ngModel.$setViewValue('0%', 'click');
ngModel.$render();
}
elem.on('click', listener);
}
};
}
angular.module('sample-app', [])
.directive('parentWithModel', ParentWithModelDirective)
.directive('childOfParent', ChildOfParentDirective)
.directive('anotherChildOfParent', AnotherChildOfParentDirective)
}());
<script src="http://code.angularjs.org/1.3.0/angular.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"
rel="stylesheet" />
<div class="container" ng-app='sample-app' ng-init="progressValue = 30">
<div class="masthead">
<h3 class="text-muted">Sample App
</h3>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label>Progress Value</label>
<input type="text" class="form-control" ng-model="progressValue" />
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<parent-with-model ng-model="progressValue">
<h1><code>progressValue = {{progressValue}}</code></h1>
<child-of-parent></child-of-parent>
<another-child-of-parent></another-child-of-parent>
<br />
<br />
</parent-with-model>
</div>
</div>
<!-- Site footer -->
<div class="footer">
<p>by <a href="http://www.technofattie.com">Techno Fattie</a>
</p>
</div>
</div>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句