连续模板 - 找不到指令“mdRadioButton”所需的控制器“mdRadioGroup”
Contidional template - Controller 'mdRadioGroup', required by directive 'mdRadioButton', can't be found
我正在尝试构建自定义指令,以允许我在调查中显示问题。因为我有多种类型的问题,所以我考虑过创建单个指令并根据问题类型更改其模板。
我的指令:
directive('question', function($compile) {
var combo = '<div>COMBO - {{content.text}}</div>';
var radio = [
'<div>RADIO - {{content.text}}<br/>',
'<md-radio-group layout="row" ng-model="content.answer">',
'<md-radio-button ng-repeat="a in content.answers track by $index" ng-value="a.text" class="md-primary">{{a.text}}</md-radio-button>',
'</md-radio-group>',
'</div>'
].join('');
var input = [
'<div>INPUT - {{content.text}}<br/>',
'<md-input-container>',
'<input type="text" ng-model="content.answer" aria-label="{{content.text}}" required md-maxlength="10">',
'</md-input-container>',
'</div>'
].join('');
var getTemplate = function(contentType) {
var template = '';
switch (contentType) {
case 'combo':
template = combo;
break;
case 'radio':
template = radio;
break;
case 'input':
template = input;
break;
}
return template;
}
var linker = function(scope, element, attrs) {
scope.$watch('content', function() {
element.html(getTemplate(scope.content.type))
$compile(element.contents())(scope);
});
}
return {
//require: ['^^?mdRadioGroup','^^?mdRadioButton'],
restrict: "E",
link: linker,
scope: {
content: '='
}
};
})
在我的主控制器中,我有问题列表,单击按钮后,我正在设置分配给我的指令的当前问题。
第一个问题一切正常,但是在我将当前问题设置为无线电类型后,我收到此错误:
错误: [$compile:ctreq] 控制器"mdRadioGroup",由 指令"mdRadioButton",找不到!
我尝试将required
添加到我的指令中,如下所示,但没有帮助。
require: ['^mdRadioGroup'],
我不知道发生了什么,因为我对角度还很陌生。
我创建了 Plunker 来显示我的问题:http://plnkr.co/edit/t0HJY51Mxg3wvvWrBQgv?p=preview
重现此错误的步骤:
- 打开普伦克
- 单击
Next
按钮两次(以导航到问题 3) - 查看控制台中的错误
编辑:
我已经编辑了我的 Plunker,所以我的问题模型是可见的。我能够选择答案,即使在抛出错误问题模型正在更新的问题中也是如此。但是在回答问题 3 时我仍然遇到错误。
我只是简单地扩展一个基本指令,然后还有一个具有不同指令名称的专用指令。
// <div b></div>
ui.directive('a', ... )
myApp.directive('b', function(aDirective){
return angular.extend({}, aDirective[0], { templateUrl: 'newTemplate.html' });
});
代码取自 https://github.com/angular/angular.js/wiki/Understanding-Directives#specialized-the-directive-configuration
工作演示
无需根据您的要求创建和使用指令。
您可以只使用有条件的角度模板和ng-include
。
您可以在页面上创建三个模板(每个模板用于组合,广播和输入),如下所示,
<script type="text/ng-template" id="combo">
<div>COMBO - {{content.text}}</div>
</script>
并使用 ng-include
将这些模板包含在div 中。
<!-- Include question template based on the question -->
<div ng-include="getQuestionTemplate(question)">
在这里,getQuestionTemplate()
将返回应包含在此div 中的模板的 id。
// return id of the template to be included on the html
$scope.getQuestionTemplate = function(content){
if(content.type == "combo"){
return 'combo';
}
else if (content.type == "radio"){
return 'radio';
}
else{
return 'input';
}
}
就这样。大功告成。
请随时问我对此有任何疑问。
如果有人想知道,问题是父组件的作用域用于编译每个新元素。即使删除了元素,该作用域上的绑定仍然存在(除非被覆盖),这可能会导致 OP 看到的错误(甚至更糟的是,内存泄漏)。
这就是为什么在命令性地操作元素的HTML内容时应该注意清理的原因,就像这样。而且因为这很难做到正确,所以通常不鼓励这样做。大多数用例应该由内置指令涵盖(例如 ngSwitch
OP的情况),负责自己清理。
但是,您可以在简化的方案中手动清理(如此处所示)。在最简单的形式中,它涉及为每个已编译的内容创建一个新的子范围,并在删除该内容后将其销毁。
以下是修复 OP 的 plunker 所需的方法:
以前
scope.$watch('content', function () {
element.html(getTemplate(scope.content.type));
$compile(element.contents())(scope);
});
后
var childScope;
scope.$watch('content', function () {
if (childScope) childScope.$destroy();
childScope = scope.$new();
element.html(getTemplate(scope.content.type));
$compile(element.contents())(childScope);
});
这是固定版本。
了一下你的代码,发现发生错误的原因是因为第三个问题比第二个问题得到更多的答案,所以当你第一次创建 mdRadioGroup 时,它定义了 4 个$index答案,后来对于问题 3,它超出了界限,有 6 个答案......因此,一个不优雅的解决方案是创建尽可能多的$index,第一次,只显示带有文本的答案......
.directive('question', function($compile) {
var combo = '<div>COMBO - {{content.text}}</div>';
var radio = [
'<div>RADIO - {{content.text}}<br/>',
'<md-radio-group layout="row">',
'<md-radio-button ng-repeat="a in content.answers track by $index" ng-show={{a.text!=""}} value="{{a.text}}" class="md-primary">{{a.text}}</md-radio-button>',
'</md-radio-group>',
'</div>'
].join('');
var input = [
'<div>INPUT - {{content.text}}<br/>',
'<md-input-container>',
'<input type="text" ng-model="color" aria-label="{{content.text}}" required md-maxlength="10">',
'</md-input-container>',
'</div>'
].join('');
var getTemplate = function(contentType) {
var template = '';
switch (contentType) {
case 'combo':
template = combo;
break;
case 'radio':
template = radio;
break;
case 'input':
template = input;
break;
}
return template;
}
然后更改问题,以便在所有问题中每次都有最大答案数:
$scope.questions = [{
type: 'radio',
text: 'Question 1',
answers: [{
text: '1A'
}, {
text: '1B'
}, {
text: '1C'
}, {
text: ''
}, {
text: ''
}, {
text: ''
}, {
text: ''
}]
}, {
type: 'input',
text: 'Question 2',
answers: [{
text: '2A'
}, {
text: '2B'
}, {
text: '2C'
}, {
text: ''
}, {
text: ''
}, {
text: ''
}, {
text: ''
}]
}, {
type: 'radio',
text: 'Question 3',
answers: [{
text: '3A'
}, {
text: '3B'
}, {
text: '3C'
}, {
text: '3D'
}, {
text: ''
}, {
text: ''
}, {
text: ''
}]
}, {
type: 'combo',
text: 'Question 4',
answers: [{
text: '4A'
}, {
text: '4B'
}, {
text: ''
}, {
text: ''
}, {
text: ''
}, {
text: ''
}, {
text: ''
}]
}];
代码的其余部分是相同的。正如我之前所说,没有优雅,肯定有更好的选择,但现在可能是一个解决方案......
- 在指令控制器中使用$attrs时出现问题
- 有没有任何方法可以将控制器从文件加载到ui路由器$stateProvider中
- 从控制器返回后Ajax启动事件激发
- 获取@ResponseBody的一部分作为主干和Spring MVC控制器之间的参数
- 如何在单击复选框后调用控制器方法
- 在控制器和数据对象之间同步数据
- 将Javascript数组发送到控制器ASP.NET MVC
- 角度控制器结构
- 如何在Jquery中发布后将值从视图返回到控制器
- 将值从html传递到AngularJS控制器
- 从我的控制器返回一个不同于200的代码以触发ajax错误,这被认为是一种好的做法吗
- 从控制器继承了隔离的作用域以生成可重用的指令
- Flash Uploadify在调用我的MVC控制器时没有保留会话/授权
- 为什么不't我的变量在我的控制器中填充后在我的视图中呈现
- Nodejs API控制器,用于在API之间切换
- 如何在Angular单元测试中从另一个控制器的rootScope将方法添加到rootScope中
- 将不在模型中的数据返回到mvc控制器
- 未激发路由的控制器属性上的观察者
- 错误405:向Java控制器(Ajax)发送JSON时找不到POST方法
- ROR:如何在不重新加载浏览器的情况下从控制器获取参数