Can't get iframe element passed to Angular controller from directive

I have iframe

one that has an attribute ng-src

on and I change it often. Every time the iframe changes src

, I want to execute a function in my controller AFTER the iframe is fully loaded. Also, I want the iframe DOM element to be passed to the function.

Right now I'm using the stackoverflow directive . The callback fires when the iframe is loaded and the function in my controller is executed; but I cannot get the iframe DOM element passed as a parameter.

Here is a demo Plunkr

Html

<div ng-controller='home as main'>
    <h2>My Content Up Here</h2>

    <button ng-click="main.setIframeSource()">Load iFrame Src</button>
    <iframe iframe-onload="main.onIframeLoad(element)" 
      ng-src="{{main.currentIframeSource}}"></iframe>
</div>

      

Javascript

(function() {
  angular.module('app', [])
    .controller('home', home)
    .directive('iframeOnload', iframeOnload);

  function home() {
    var vm = this;
    vm.currentIframeSource = '';
    vm.setIframeSource = setIframeSource;
    vm.onIframeLoad = onIframeLoad;

    function onIframeLoad(element) {
      console.log(element);
    }

    function setIframeSource() {
      if (vm.currentIframeSource === '' || vm.currentIframeSource === 'iframe2.html')
        vm.currentIframeSource = 'iframe.html';
      else
        vm.currentIframeSource = 'iframe2.html';
    }

  }

  function iframeOnload() {
    var directive = {
      scope: {
        callBack: '&iframeOnload'
      },
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.on('load', function() {
          return scope.callBack(element);
        });
      }
    };

    return directive;
  }
})();

      

I tried to use $event

and passed this

as a function parameter onIframeLoad

in my HTML, but I can never get a reference to the iframe DOM element.

Thoughts?

+3


source to share


1 answer


If you want to pass data to an expression defined in isolation scope, you need to pass it through an object with named parameters. See this: https://docs.angularjs.org/api/ng/service/ $ compile # -scope -

So, in theory, all you have to do is change your directive scope.callback(element)

to:

return scope.callBack({element:element});

      

BUT Angular tries to provide a separation of concerns between what you can do in directives and what you can do in controllers. You shouldn't be doing anything with raw elements in your controllers, so Angular will prevent you from doing what I just wrote and point you to a page like this: Error: error: isecdom DOM node reference in expression



If you are deliberately breaking the rules and doing a workaround, then what you can do is wrap the element in its own object and then it will go through fine (but remember this is not recommended)

  link: function(scope, element, attrs) {
    element.on('load', function() {
      console.log('in directive iframe loaded',element);
      // bad bad bad!
      var elemWrapper = {theElem:element};
      return scope.callBack({element:elemWrapper});
    });
  }

      

I created a plunker showing this works: http://plnkr.co/edit/Oj5lkVAPXdjdNmf62YUQ?p=preview (uncomment the bad part to see the item being passed)

0


source







All Articles