0

Html

<div class="result" ng-controller="test">
    <div>{{result}}</div>
    <a ng-href="{{result}}"></a>
</div>

JS

App.controller('AppCtrl', function AppCtrl($scope){
    $scope.result = "www.google.com";
}

In a jquery file I can't modify because of some reason, some code changed the value of href, like:

$('.result>a').attr('href','www.youtube.com');

I want the value of $scope.result in the controller also changed from "www.google.com" to "www.youtube.com". But the result value in the div didn't change after the jquery code. Do I need write directive to watch the href attribute by myself? Or there are some other way to use ng-href? I try to write the directive by myself, but it didn't work. I hope you can give me a small example. Thanks :)

Update:

This is my directive, it didn't work, after something like $('.result>a').attr('href','www.youtube.com'), the console didn't print "change!" and the $scope.result didn't change:

APP.directive('result', function() {
    return {
        restrict: 'E',
        scope: {
            ngModel: '='
        },
        template: "<div class='result'><a ng-href='{{ngModel}}' href=''></a></div>",
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attrs) {
            var $element = $(element.children()[0]);
            scope.$watch($element.attr('href'), function(newValue) {
                console.log("change!");
                scope.ngModel = newValue;
            })
        }
    };
});

Update Again: Still can't work...

Html:

<div class="result">
    <a ng-href="{{result}}" ng-model="result" class="resulta"></a>
</div>

JS:

APP.directive('resulta', function() {
    return {
        restrict: 'C',
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs) {
            scope.$watch(attrs.href, function(newValue) {
                console.log("change!");
                scope.ngModel = newValue;
            })
        }
    };
});
user2655973
  • 315
  • 3
  • 13

1 Answers1

0

You can indeed create a custom directive to do it. See the example. I use transclude scope so you can put whatever you like in the link. I set 'replace: true' so the directive is removed and replaced with the <a>.

UPDATE Using MutationObserver to watch for changes to the <a href>

var app = angular.module("MyApp", []);

app.directive("myHref", function() {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    link: function(scope, elem, attrs) {
      var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
          scope.$parent.result = mutation.target.href;
          scope.$apply();
        });
      });

      // configuration of the observer:
      var config = {
        attributes: true,
        childList: true,
        characterData: true
      };

      observer.observe(elem[0], config);

    },
    scope: {
      myHref: '='
    },
    template: '<a target="_blank" ng-transclude href="{{myHref}}"></a>'
  };
});

app.controller('AppCtrl', function($scope) {
  $scope.result = "http://www.yahoo.com";
  $scope.$watch('result', function() {
    alert($scope.result);
  });
});



setTimeout(function() {
  $('.result > a ').attr('href', 'http://www.youtube.com');
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div ng-app="MyApp">
  <div class="result" ng-controller="AppCtrl">
    <my-href my-href="result">My Link</my-href>
  </div>
</div>
Harold Ship
  • 989
  • 1
  • 8
  • 14
  • I tried, but see the $scope.result still not change. You can see in: http://jsfiddle.net/castiel_zyf/0hL4ucxf/ – user2655973 Mar 17 '15 at 17:40
  • yes I saw your changes after I uploaded my solution. – Harold Ship Mar 17 '15 at 18:16
  • updated now with MutationObserver now updates the $scope.result – Harold Ship Mar 17 '15 at 18:51
  • Thanks a lot, this really worked! But I am curious about why the function like scope.$watch() didn't work, is there some problem in my code? Or the $watch function can't achieve the desired results like MutationObserver? – user2655973 Mar 18 '15 at 02:16
  • The jQuery function is called outside the control of AngularJS. This means, that all of the _magic_ that AngularJS does with calling watchers, etc. won't happen automatically. This article here [http://www.sitepoint.com/understanding-angulars-apply-digest/](http://www.sitepoint.com/understanding-angulars-apply-digest/) explains it quite well. In fact after perusing it, I see I should have called `$apply` instead of `$digest`, and so I've changed it. – Harold Ship Mar 18 '15 at 04:20