Your really close. First I'll give you what your probably looking to do since I do not know your intentions for the $compile service. Then I'll explain why you don't need the $compile service for this particular instance since your effectively duplicating ng-include.
What your probably looking to do:
The key to using directives (especially when attempting to "$compile" dynamic content is ensuring your know what scope is passed where. For most of the directives built into angularjs, angular automatically handles creation (via scope.$new() ) and destruction (via scope.$destroy() ). Since you are not explicitly '$destroy'-ing the scopes they will not be removed. Another problem is that your directly attaching the "dynamic" directive to the current scope without creating a child scope or an isolate scope in the directive (via $new):
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var curScope = null,
curEle = null;
function removeOld(){
if( curScope ){
curScope.$destroy();
curScope = null;
curEle.remove();
curEle = null;
}
}
scope.$watch(attrs.dynamic, function(html) {
removeOld();
curScope = scope.$new(); //creates child scope (not isolate)
//probably should do some proper escaping here see $sce service
curEle = angular.element( html );
if( !curEle.length ){
curEle = angular.element('<span>'+html+'</span>');
}
$compile( curEle )(curScope);
element.append( curEle );
});
}
};
});
What you probably should do:
For some small templates like this you probably should consider putting them into the $templateCache (via put as shown in the plunkr below) so that any request for the template can automatically load it. You also have to consider some other things like 'is the html properly sanitized?' or 'do I want my content animated properly?'. These things are automatically handled in ng-include which it almost seems like your trying to copy.
app.run(function( $templateCache ){
$templateCache.put("btn_default.html", "Default content");
$templateCache.put("btn_one.html", "<div ng-controller='FirstCtrl'>The div from first button</div>");
$templateCache.put("btn_two.html", "<div ng-controller='SecondCtrl'>The div from second button</div>");
})
Now all you have to do is use the pre-built ng-include directive like so:
<div ng-controller="TestCtrl">
<div class="btn btn-default" ng-click="firstButton()">First button</div>
<div class="btn btn-default" ng-click="secondButton()">Second button</div>
<div class="btn btn-default" ng-click="checkButton()">Check events</div>
<div ng-include="dynamicContent"></div>
</div>
ng-include source to help you out
Hope this helps with a better understanding.