2

I have an external JSON file which is a collection of buttons/actions like this

   {  
   "foo1":{  
      "name":"productDetails",
      "displayAs":"button",
      "action":"viewDetails()"
   },
   "foo2":{  
      "name":"sell",
      "displayAs":"button",
      "action":"sellProduct()"
   }
}

Later, in my view, I create a <div> using ng-repeat for each object contained in that JSON.

My question is, can I set the ng-click property as it it in the JSON file like this?

<li ng-repeat = "field in fields">
    <div ng-click = field.action > {{field.name}} </div>
</li>
4
  • 1
    Why don't you try and check if you can do it or not? Commented Mar 23, 2017 at 14:07
  • 2
    If you just use the function name in your json (like action: 'viewDetails'), ou could use $scope[field.action]() or this[field.action](), depending on how your controller is organized, or use an if/else tree: if (field.action === 'viewDetails()') $scope.viewDetails() Commented Mar 23, 2017 at 14:08
  • 2
    Yes, you can, you'll have to change your data slightly though. Do as @DevDig has said. Here is a fiddle Commented Mar 23, 2017 at 14:12
  • @KOUSIKMANDAL I wouldn't post this if I didn't try it, don't you think? :) Commented Mar 23, 2017 at 14:34

1 Answer 1

1

you can do this using ng-bind-html.

 <li ng-repeat = "field in fields">
    <div bind-html-compile ng-bind-html="trust(field)"  >  </div>
  </li>

Add bind-html-compile directive to compile the DOM so that changes will effect to DOM elements

Directive

 .directive('bindHtmlCompile', ['$compile', function($compile) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            scope.$watch(function() {
                return scope.$eval(attrs.bindHtmlCompile);
            }, function(value) {
                element.html(value);
                $compile(element.contents())(scope);
            });
        }
    };
 }]);

In trust function pass the object as an argument and return the html trust element

 $scope.trust = function(html) {
    return $sce.trustAsHtml('<div ng-click = "' + html.action + '" > {{field.name}} </div>');
 }

Demo

angular.module("app",[])
.controller("ctrl",function($scope,$sce){

$scope.viewDetails = function(){console.log("viewDetails")}
$scope.sellProduct = function(){console.log("sellProduct")}
$scope.fields =    {  
   "foo1":{  
      "name":"productDetails",
      "displayAs":"button",
      "action":"viewDetails()" 
   },
   "foo2":{  
      "name":"sell",
      "displayAs":"button", 
      "action":"sellProduct()"
   }
}

$scope.trust = function(html){

return $sce.trustAsHtml('<div ng-click = "'+html.action+'" > {{field.name}} </div>');

}


}).directive('bindHtmlCompile', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function () {
                    return scope.$eval(attrs.bindHtmlCompile);
                }, function (value) {
                    element.html(value);
                    $compile(element.contents())(scope);
                });
            }
        };
    }]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
 <li ng-repeat = "field in fields">
    <div bind-html-compile ng-bind-html="trust(field)"  >  </div>
</li>
</div>

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

3 Comments

why ng-bind-html has trust(field), it has been designed to put html inside element..
Trust function return html so that ng bind html will bind that
I'd suggest to do simpler way this commented

Your Answer

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