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?

3
  • 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. Commented Aug 5, 2016 at 12:22
  • See this answer how to achieve this Commented Aug 5, 2016 at 12:23
  • @devqon problem with that is that it is uisng $watch which when used with ng-repeat can give an error Commented Aug 5, 2016 at 12:46

2 Answers 2

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/

Sign up to request clarification or add additional context in comments.

1 Comment

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 <code>HTML</code>string with <p style="color: {{element.color}}">color</p>
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>

3 Comments

sadly i cant do the above i need the whole html to be a javascript string
$compile then is probably your go to.
could you give an example?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.