Reputation: 7269
I have some some service. I wanna to debug it and see state of variables in this service. My code is below (explanation below the code):
module.factory('Data', function () {
var current = [], unlocked = [], all = [];
return {
current: current,
unlocked: unlocked,
total: all
}
});
module.controller('debugPlaneController', ['$scope', 'Data', function ($scope, data) {
$scope.data = data;
}]);
module.factory('someService', ['Data', function (data) {
var initDebugMode = function () {
var style = "style='width: 500px; height: 100px; background-color: #ccc;";
var template = "
<div "+style+" ng-controller='debugPlaneController'>
<p>data.current = {{ data.current }}</p>
<p>data.total = {{ data.total }}</p>
<p>data.unlocked= {{ data.unlocked }}</p>
</div>
";
$(".someClass > .childClassOfSomeClass").append(template);
};
// some more methods, for example
var push = function (name) {
data.current.push(name);
data.all.push(name);
}
// etc
return {
initDebug: initDebugMode,
push: push
// some more methods
}
}]);
module.controller('mainController', ['$scope', 'someService', function($scope, someService) {
someService.initDebug();
someService.push('lala');
});
So, I have some app with controller mainController
. I want to use service someService
in it. I am using push
method. This method pushes data from name
argument to total
and current
arrays of Data service Data
. As you see, I called method initDebug()
from mainController
, so I want debug window to appear on my screen. I want to show state of arrays current
, total
and unlocked
of Data
data-service.
Actually, window appears on screen, but I see this on it:
data.current = {{ data.current }}
data.total = {{ data.total }}
data.all = {{ data.all }}
So, AngularJS templates wasn't interpolated. How I can make them interpolating + I need live update of them in this block (like angularJS actually do).
Using $compile.
So I need to change my initDebugMode
function this way?:
module.factory('someService', ['Data', '$compile', function (data, $compile) {
var initDebugMode = function () {
var style = "style='width: 500px; height: 100px; background-color: #ccc;";
var scopeImitation = { data: data };
var template = "
<div "+style+" ng-controller='debugPlaneController'>
<p>data.current = {{ data.current }}</p>
<p>data.total = {{ data.total }}</p>
<p>data.unlocked= {{ data.unlocked }}</p>
</div>
";
$compile(template)(scopeImitation);
$(".someClass > .childClassOfSomeClass").append(template);
};
// etc...
]);
How exactly passing variable to 2nd brackets in $compile
service works? I used this correctly?
Upvotes: 1
Views: 1383
Reputation: 16435
You need to use the $compile service:
Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.
You would use it like:
$compile(template)($scope);
Don't forget to inject the $compile
service and $scope
into your factory first though.
I would also read through this post to understand the other angular services you could use to achieve your goals:
What is the difference between the $parse, $interpolate and $compile services?
Because $interpolate
might be more suited to what you're trying to do, but $compile
is the most powerful.
At first I didn't really take proper notice of the fact that you were inside a factory. I think it is generally inadvisable (maybe impossible?) to pass the scope into into the factory. If you want a reuseable debug interface, I think the best way would not to be putting it in your factory, but instead, making a directive:
module.directive('debug' , function() {
return {
restrict: 'E',
template:'<div><p>data.current = {{ data.current }}</p><p>data.total = {{ data.total }}</p><p>data.unlocked= {{ data.unlocked }}</p></div>',
controller: 'debugPlaneController'
}
});
I removed the style
from your template because you can actually style the directive from your css by defining a css rule for debug
debug > div {
width: 500px;
height: 100px;
background-color: #ccc;
}
And I removed ng-controller
from your template because your directive will use the controller defined in the directive.
Now you can put your directive wherever you want like this. It'll generate the template inside correctly without you having to worry about $compile:
<debug></debug>
Moreover if you want to only show it conditionally you could use ng-if
<debug ng-if="debugMode == true"></debug> //debugMode would be a variable you defined in your controller
Also regarding your question for $compile
and your scopeImitation
I've never seen it used that way before and I don't think that would work. $compile
from what I've seen is always written as $compile(thing to compile)($scope)
Upvotes: 1