Reputation: 637
I'm generating a report with collection of questions.
app.controller('reportCtrl', ['$scope','$stateParams', function ($scope, $stateParams) {
$scope.questions: [
{ questionkey: 1, questiontext: 'Type', questiontype: 1 , questionmodel:'accsType' },
{ questionkey: 2, questiontext: 'Reported By', questiontype: 1, questionmodel: 'accsReportedBy' },
{ questionkey: 3, questiontext: 'Time and Date', questiontype: 6, questionmodel: 'accsCurrentDate' },
{ questionkey: 4, questiontext: 'Address', questiontype: 2, questionmodel: 'accsAddress' },
{ questionkey: 5, questiontext: 'Coordinates', questiontype: 6, questionmodel: 'accsCoordinates' },
{ questionkey: 6, questiontext: 'Blank', questiontype: 1, questionmodel: 'accsBlank1' },
{ questionkey: 7, questiontext: 'Blank', questiontype: 1, questionmodel: 'accsBlank2' },
{ questionkey: 8, questiontext: 'Blank', questiontype: 1, questionmodel: 'accsBlank3' },
{ questionkey: 9, questiontext: 'Blank', questiontype: 1, questionmodel: 'accsBlank4' },
{ questionkey: 10, questiontext: 'Details of Survey', questiontype: 2, questionmodel: 'accsDetailsSurvey' },
{ questionkey: 11, questiontext: 'Photos', questiontype: 5, questionmodel: 'accsPhotos' }
];
}]);
and I've created a custom directive to draw the questions according to the question types Eg question type 1 is text box type 2 is textarea
<question contents="questions"></question>
app.directive('question', function ($compile) {
return {
transclude: true,
restrict: 'E',
scope: {
contents: '='
},
link: function (scope, element, attrs) {
angular.forEach(scope.contents, function (k, v) {
var ele;
switch (parseInt(k.question.questiontype)) {
case 1:
ele = $compile("<accstextbox data='k.question'></accstextbox>")(scope);
break;
case 2:
ele = $compile("<accstextarea data='k.question'></accstextarea>")(scope);
break;
}
element.append(ele);
});
}
};
});
I've created a directive for each question types
app.directive('accstextbox', [function () {
return {
restrict: 'E',
templateUrl: 'app/directives/questions/textbox.html',
link: function (scope, element, attrs) {
console.log(scope.data); // undefined
},
scope:{
data: '='
}
};
}]);
app.directive('accstextarea', [function () {
return {
restrict: 'E',
templateUrl: 'app/directives/questions/textarea.html',
link: function (scope, element, attrs) {
console.log(scope.data); // undefined
},
scope: {
data: '='
}
};
}]);
when i dynamically add those directives, i'm passing the data object via attribute. that data object is undefined in the child directive scope. first time i'm using angularjs for my project.
Upvotes: 3
Views: 621
Reputation: 532
As Vinicius noted, you're using the k
object inside the forEach
loop in a text string so angular can't resolve what you mean by k.questions
.
I propose a similar solution to repeat the questions in an ng-repeat inside your question
directive:
<div>
<div ng-repeat="q in contents">
<div ng-switch="q.questiontype">
<div ng-switch-when="1">
<accstextbox> one: {{q.questiontext}}</accstextbox>
</div>
<div ng-switch-when="2">
<accstextarea> two : {{q.questiontext}}</accstextarea>
</div>
</div>
</div>
</div>
Another option is to move the logic of selecting the type of template into the child directive. I would prefer this option if your only change is the type of input, and there is not much difference in the logic, so you would avoid duplicating your code, i.e the child directive template would contain the input selection logic:
<div>
<div ng-if="question.questiontype === 1">
<input type="text"/>
</div>
<div ng-if="question.questiontype === 2">
<textarea name="" id="" cols="30" rows="10"></textarea>
</div>
</div>
Upvotes: 1
Reputation: 2239
Your solution will not work since k
is a local variable and is no accessible for the $compiler
service.
A solution for this is to make your directive use ngRepeat
and ngIf
to generate the final layout through templates:
app.directive('question', function ($compile) {
return {
transclude: true,
restrict: 'E',
templateUrl: 'app/directives/questions.html',
scope: {
contents: '='
}
};
});
And the app/directives/questions.html
:
<div ng-repeat="question in contents">
<accstextbox ng-if="question.questiontype == 1" data="question"></accstextbox>
<accstextarea ng-if="question.questiontype == 2" data="question"></accstextarea>
</div>
Since this is a really small template, you may add it to the template
configuration parameter of the directive, instead of loading it from the server through templateUrl
.
Hope this will help you!
Upvotes: 1