1

I am getting some response from my service. The response is in the form of

 "My data <my-tag>Click me</my-tag>".

The response contains the tag "my-tag". I want to write a directive which would manipulate the content "Click me" within the tag whenever the response is rendered. The content within the custom tag should be converted into a hyperlink. How can I do this? Here is my sample code.

I have myService.js

Service.js

(function() {
    function myService() {
        this.getData = function(question,questionType) {
        anotherService.getList(function(data, status) {   
 //Here data.text = "<my-tag>Click me</my-tag>"            
                   document.getElementById("additionalData").innerHTML + data.text;
            });                         
        }                           
    }
    app.addService(app.config.modules.MY_MODULE, "myService", myService);
}());

Directive.js

(function() {
    app.directive('myTag', function () {
        debugger;
        return {
            link: function ($scope, element, attrs) {
                debugger;
                //Convert the text "Click me" into hyperlink
            }
        };
    });
}());

myHtml.html

<html ng-app = "myApp">
        <head>
            <script>
                app.inject(app.config.modules.MY_MODULE, "myService", function(instance) {
                    myService = instance;
                    console.log("myService dependency injected successfully.");
                });
            </script>
        </head>
        <body ng-controller="myCtrl">
            <div>
                <img id="getList" onclick="myService.getData()">
            </div>
        </body>
    </html>
Lotus91
  • 1,127
  • 4
  • 18
  • 31
ASR
  • 421
  • 11
  • 27
  • This post might help http://stackoverflow.com/questions/14692640/angularjs-directive-to-replace-text – Kobi Cohen Apr 25 '16 at 13:16
  • Yeah, I have seen this post. In my case the control does not even enter the link function. I tried converting the element tag "my-input" into an attribute instead of an element. That does not work either. – ASR Apr 25 '16 at 13:21
  • 1
    In your directive look into using the $compile service and replace the link function's element with the result, e.g. element.replaceWith($compile(element)($scope)) or element.replaceWith(newHtml)($scope)) – RamblinRose Apr 25 '16 at 13:24

1 Answers1

1

You need to compile the response that you receive as text in order to make myTag working, otherwise link function of myTag will not be invoked at all.

The general idea should be to avoid manipulating DOM directly and leave this task to directives. So the best way of rendering some data that comes afterwards would be to modify model (scope) and react to these changes in directive that applied to element that should contain the data to be rendered.

Here is one of possible solutions:

HTML

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.5.3" data-semver="1.5.3" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <h1>Hello Plunker!</h1>
    <my-list></my-list>
  </body>

</html>

JavaScript

angular.module('app', [])
  .directive('myTag', function() {
    return {
      transclude: true,
      template: '<a href="#" ng-transclude></a>'
    }
  })
  .directive('myList', ['$compile', function($compile) {
    return {
      template: '<ul></ul>',
      link: function(scope, element) {
        scope.$watchCollection('data', function(data) {
            if(data && data.length) { 
              element.empty(); 
              data.forEach(function(item) {
                element.append( 
                  $compile( // <= in order to make myTag directive work, you need to compile text
                    angular.element('<p>'+item+'</p>').contents() // convert text to list of DOM elements wrapped by jqLite/jQuery
                  )(scope)
                );
              });
            }
          }
        );
      }
    }
  }])
  .run(['$http', '$rootScope', function($http, $rootScope) {
    $rootScope.data = []; 
    $http.get('data.txt').then(function(xhr) { 
      $rootScope.data.push(xhr.data);
    });
  }]);

Plunker

https://plnkr.co/edit/VOl8P7r2DpnayMjRWbvI?p=preview

Vadim
  • 8,701
  • 4
  • 43
  • 50