I'm attempting to create a Showdown extension in my Angular app which will show scope variables. I was able to get it setup to show basic scope variables easily enough, but now I'd like to get it to where I can use the results of an ng-repeat
and I can't get anything other than [[object HTMLUListElement]]
to show.
Here's my controller so far:
app.controller('MyCtrl', ['$scope', '$window', '$compile', function($scope, $window, $compile){
$scope.machines = [
{ abbv: 'DNS', name: 'Did Not Supply' },
{ abbv: 'TDK', name: 'The Dark Knight' },
{ abbv: 'NGG', name: 'No Good Gofers'}
];
$scope.machine = $scope.machines[0];
$scope.machine_list = $compile('<ul><li ng-repeat="m in machines">{{m.abbv}}: {{m.name}}</li></ul>')($scope);
$scope.md = "{{ machine_list }}";
var scopevars = function(converter) {
return [
{ type: 'lang', regex: '{{(.+?)}}', replace: function(match, scope_var){
scope_var = scope_var.trim();
return $scope.$eval(scope_var);
}}
];
};
// Client-side export
$window.Showdown.extensions.scopevars = scopevars;
}]);
Plunkr: code so far
I feel like I've got to be close, but now I don't know if I'm on the completely wrong track for this, or if it's a showdown thing or an angular thing or what.
I realized I was fighting Angular (and losing quiet badly) with the way I was doing that. DOM in a controller is a no-no. And now I'm kind of angry about how easy it is once I started thinking properly and looking at the directive.
Now instead of trying to do the compile and everything within the controller, I included the $compile
service in the directive I'm using, so:
htmlText = converter.makeHtml(val);
element.html(htmlText);
became:
htmlText = converter.makeHtml(val);
element.html(htmlText);
$compile(element.contents())(scope);
With that change in place I no longer need the portion of the extension that just did the basic evaluation, since it's being compiled {{ machine.name }}
is automatically converted.
But that still left me not being able to specify a variable to insert a template, just variables. But now that the output is going to be compiled through angular I can put the template in a partial and use an extension to convert from a pattern to an ng-include
which works.
New Controller Code:
app.controller('MyCtrl', ['$scope', '$window', '$compile', function($scope, $window, $compile){
$scope.machines = [
{ abbv: 'DNS', name: 'Did Not Supply' },
{ abbv: 'TDK', name: 'The Dark Knight' },
{ abbv: 'NGG', name: 'No Good Gofers'},
{ abbv: 'TotAN', name:'Tales of the Arabian Nights'}
];
$scope.machine = $scope.machines[0];
$scope.tpls = {
'machinelist': 'partials/ml.html'
};
$scope.md = "{{machines.length}}\n\n{{include machinelist}}";
var scopevars = function(converter) {
return [
{ type: 'lang', regex: '{{include(.+?)}}', replace: function(match, val){
val = val.trim();
if($scope.tpls[val] !== undefined){
return '<ng-include src="\''+$scope.tpls[val]+'\'"></ng-include>';
} else {
return '<pre class="no-tpl">no tpl named '+val+'</pre>';
}
}}
];
};
// Client-side export
$window.Showdown.extensions.scopevars = scopevars;
}]);
And of course the new plunkr
Hope this can help someone later down the road