htmlangularjsangular-ui-routerui-sref

Dynamic ui-sref in directive template Angular Js


In my angular js Application, I have a directive inside a ng-repeat. Directive has a template in which the HTML part is loaded. Inside that template I am declaring a ui-sref Router dynamically setting states!

This does not Work!

I have tried a Fiddle

Without using a Directive ui-sref works Fine. But I need it in Directive's template.

MY HTML PART

<div ng-repeat="sp in obj.PEs">
  <div draw-pe proc="{{sp.peId}}"></div>
</div>

<div style="border:1px;" ui-view="properties"></div>

My Script Part

var myApp = angular.module('myApp', ["ui.router"]);
myApp.controller("testCtrl", function($scope) {
  $scope.obj = {
    "PEs": {
      "1": {
        "peId": "1",
        "peName": "Exp1",
        "peDisplayName": "Exp",
        "peType": "Exp",
        "peCategory": "PE"
      },
      "2": {
        "peId": "2",
        "peName": "RN1",
        "peDisplayName": "RNull",
        "peType": "RN",
        "peCategory": "PE"
      }
    }
  }
})

myApp.config(function($stateProvider, $urlRouterProvider) {
  $urlRouterProvider.otherwise('/');
  $stateProvider
    .state('Exp', {
      url: '/Exp/:peId',
      views: {
        "properties": {
          template: ".<h3>I am Exp ! </h3>",
          controller: function($scope, $stateParams) {
            var peId = $stateParams.peId;
            alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));

          }
        }
      }
    })
    .state('RN', {
      url: '/RN/:peId',
      views: {
        "properties": {
          template: "<h3> I am RN ! </h3>",
          controller: function($scope, $stateParams) {
            var peId = $stateParams.peId;
            alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));
          }
        }
      }
    })
});
myApp.directive("drawPe", function() {
  return {
    restrict: "AE",
    template: '<div ui-sref="{{peObj.peType}}( { peId:peObj.peId } )"> <h5>{{peObj.peDisplayName}}</h5></div>',
    link: function($scope, element, attrs) {
      var procId = $scope.$eval(attrs.proc);
      alert(procId);
      // alert(angular.toJson(scope.obj.processElements[procId]))
      $scope.peObj = $scope.obj.PEs[procId];
    }
  }
})

See the Browser Console, on clicking the output Part!

ERROR

Error: Invalid state ref '( { peId:peObj.peId } )'

What will be the best Practice to call dynamic state names inside directives Template? I Have read some previous asked question and answer, But I am not clear with the idea as I am new to Angular Js.

Any Idea/help appreciated

Thanks


Solution

  • You can use $compile service to compile your directive's template when your scope changes.

    Your directive could look like this:

    myApp.directive("drawPe", function($compile) {
    
    return {
     restrict: "AE",
     tranclude: true,
     scope: {
       peObj: '='
     },
     template: '<a href="" ui-sref="{{peObj.peType}} ({peId: peObj.peId})"> <h5>{{peObj.peDisplayName}}</h5></a>',
     link: function(scope, element, attrs) {
      console.log(scope.peObj);
      scope.$watch(
        function(scope) {
          // watch the 'compile' expression for changes
          //return scope.$eval(attrs.compile);
        },
        function(value) {
          $compile(element.contents())(scope);
        }
      );
      }
     }
     });
    

    And your html:

    <div ng-repeat="sp in obj.PEs">
      <div draw-pe pe-obj="sp" proc="{{sp.peId}}"></div>
    </div>
    
    <div style="border:1px;" ui-view="properties"></div>
    

    Working fiddle is here.