Contidional template - The controller 'mdRadioGroup' required by the 'mdRadioButton' directive cannot be found

I am trying to create a custom directive that will allow me to display questions in a survey. Since I have several types of questions, I thought about creating a single directive and changing its template based on the type of question.

my directive:

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: '=' } }; }) 

Inside my main controller, I have a list of questions, and after clicking the button, I ask the current question, which is assigned to my directive.

Everything works fine for the first questions, but after I set the current question to the radio type, I get this error:

Error: [$ compile: ctreq] The controller 'mdRadioGroup', the required directive 'mdRadioButton', could not be found!

I tried adding required to my directive as shown below, but that didn't help.

 require: ['^mdRadioGroup'], 

I cannot understand what is happening because I am still new to angular.

I created Plunker to show my problem: http://plnkr.co/edit/t0HJY51Mxg3wvvWrBQgv?p=preview

Steps to reproduce this error:

  • Open plunker
  • Click Next twice (to go to question 3)
  • See console error message

EDIT:
I edited my Plunker, so my question model is visible. I can choose answers, even in questions that cause modification of error models. But still, I get an error when going to question 3.

+7
javascript angularjs angular-material
source share
3 answers

I would just extend the base directive and then also have specialized names with different directive names.

 // <div b></div> ui.directive('a', ... ) myApp.directive('b', function(aDirective){ return angular.extend({}, aDirective[0], { templateUrl: 'newTemplate.html' }); }); 

Code taken from https://github.com/angular/angular.js/wiki/Understanding-Directives#specialized-the-directive-configuration

+3
source share

Working demo

There is no need to create and use a directive for your requirement.

You can simply use the angular and ng-include templates with the condition.

You can simply create three templates on your page (each for combo, radio and input),

 <script type="text/ng-template" id="combo"> <div>COMBO - {{content.text}}</div> </script> 

And include these patterns in the div using ng-include .

 <!-- Include question template based on the question --> <div ng-include="getQuestionTemplate(question)"> 

Here getQuestionTemplate() will return the identifier of the template that should be included in this div.

 // 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'; } } 

It's all. You did it.

Please feel free to ask me about this.

+3
source share

I played a little with your code and found that the reason the error occurred was because the third question received more answers than the second, so when you create mdRadioGroup, for the first time it determines 4 $ index answers, and then for question 3 it comes out of 6 answers ... Thus, it is not an elegant solution to create as many $ index as possible than the maximum number of answers to any question, for the first time only those that have text are shown ...

 .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; } 

then change the questions to have the maximum number of answers each time in all questions:

 $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: '' }] }]; 

The rest of the code is the same. As I said, there are no elegant ones and there are probably better options, but it may be a solution at the moment ...

+2
source share

All Articles