2

I am creating a directive where you are able to pass different type of html elements and inject them into a table.

However sometimes my users might need to add some kind of expression to the ng-class directive

check for instance the following:

$scope.element =        
  {
    html: '<button type="button" ng-class="element.classExpression">My  button</button>',
    classExpression : "element.classExpressionDefault ? 'btn-success': 'btn-danger'",
    classExpressionDefault: $scope.inactive,
   }

HTML:

<span ng-bind-html-unsafe="element.html">  </span>

Please note the above code does not work!

The problem with the above code is that the expression is not being evaluated and therefor it goes lost.

So my question is how may i add it and is it possible?

HiDeoo
  • 10,353
  • 8
  • 47
  • 47
Marc Rasmussen
  • 19,771
  • 79
  • 203
  • 364
  • I think this is because angular only injects clean html and handles it as such. It does not handle it as angular compiled html, so it won't evaluate any expressions inside it. – devqon Aug 05 '16 at 12:22
  • See [this answer](http://stackoverflow.com/a/29994559/3153169) how to achieve this – devqon Aug 05 '16 at 12:23
  • @devqon problem with that is that it is uisng $watch which when used with ng-repeat can give an error – Marc Rasmussen Aug 05 '16 at 12:46

2 Answers2

1

As Brant already hints at in his answer you can compile the html of the $scope.element from within your directive to evaluate angular expressions.

For that purpose you need to inject the $compile service and call it with the directives $scope on the element.html:

angular.module('ui.directives', []).directive('exampleDirective', ['$compile',
function ($compile) {
    return {
        restrict: 'E',
        scope: { element: '=' },
        template: '<span ng-bind-html-unsafe="element.html"></span>',
        link: function ($scope, element, attrs, controller) {
            $scope.element = {
                html: 'I am an <code>HTML</code>string with <p style="color: {{element.color}}">color</p>',
                color: 'red'
            }
            $scope.element.html = $compile($scope.element.html)($scope);
        }
    };
}]);

Of course you can then pass in the element via the template that uses the directive and have it defined the parent controller:

$scope.element = {
            html: 'I am an <code>HTML</code>string with <p style="color: {{element.color}}">color</p>',
            color: 'red'
        }

Template:

<example-directive element="element"></example-directive>

JSFiddle: http://jsfiddle.net/8fw1gbrt/

lcs.bdr
  • 388
  • 1
  • 9
  • i can see that it works on your fiddle however i cant make it work in my project i get the following: Error: Syntax error, unrecognized expression: I am an HTMLstring with

    color

    – Marc Rasmussen Aug 05 '16 at 13:45
0

To do what you're trying to do, you're likely going to need to inject $compile and compile elements on the fly. Another option would be to pass the options in slightly differently and configure your DOM a bit differently to react.

JSON:

$scope.inputs = [{
    type: 'text',
    classComparisonValue: 'someClass', // omit perhaps for other logic on DOM?
    model: 'myKey'
}]

And your DOM:

<div ng-repeat="input in inputs">
    <input type="text" class="input.class" 
          ng-model="inputAnswer[input.model]" 
          ng-if="input.type == 'text" 
          ng-class="{ 'btn-danger': input.classComparisonValue, 
                      'btn-success': !input.classComparisonValue">
    // Add other input types here with ng-if
</div>
Brant
  • 1,764
  • 11
  • 18