I'm writing an angularjs app (with a node/express backend). I have in my scope an object that gets populated (and repopulated) asynchronously via a service.
The contents of the object is a series of "question" objects, which for simplicity have a "text" and a "type" attribute.
What I'm trying to achieve is to be able to have an angular directive per type, and for these to render properly. So for example if the server returns [{type:'booleanquestion',text:'Is the sky blue?'}] I would create an element , and then the booleanquestion directive will kick in and render it appropriately.
So far I have defined a "questionset" directive which works well, watching the questions collection and compiling the required stuff so the directives display correclt.y
Html
<div questionset="questions"/>
app.js
...
scope.questions = questions; // e.g. [{text: 'some text',type: 'boolean'}]
directives.js
angular.module('myApp').directive('questionset',function($compile){
return {
transclude: 'true',
compile: function(element,attr,linker){
return function($scope,$element,$attr){
var elements = [],
parent = $element.parent();
$scope.$watchCollection('questions',function(questions){
var block, i, childScope;
if(elements.length > 0)
{
for( i = 0; i < elements.length ; i++)
{
elements[i].el.remove();
elements[i].scope.$destroy();
}
elements = [];
}
if(!questions) return;
for(i = 0; i < questions.length; i++)
{
childScope = $scope.$new();
childScope['question'] = questions[i];
var html = '<div class="'+questions[i].type+'"/>';
var e = angular.element(html);
block = {};
block.el = e;
block.scope = childScope;
$compile(e)(childScope);
element.append(e);
elements.push(block);
}
});
}
}
}
});
// For example, one type might be "boolean"
angular.module('myApp').directive('boolean',function($compile){
return {
restrict: 'AC',
template: '<div class="question">{{question.text}}</div>',
replace: true,
link: function(scope,elem,attrs,ctrl){
…….
// for some reason, $compile will not be defined here?
}
};
});
Whilst this is working OK, I have 2 questions
1). Is this the "right" angular way to do this? This is my first angular project and it seems I've jumped in rather at the deep end (or that's how it feels anyway)
2). My next goal is for the question.text to be able to contain HTML and for that to be "compiled". For example the text might be
"Is the <strong>sky</strong> blue?"
I'm not sure how to make this work - as my comment in the code suggest, for some reason $compile is not being injected into my boolean directive. Perhaps this is because I've manually created that child scope for it? Is it right I'm trying to $compile again the contents of the element? I feel like this last bit is probably very simple, but I'm not seeing it.