Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular : src attribute bug in Iframe directive

I'm having a problem with a Iframe directive that I try to implement.

As far I am : Template:

<div class="externalIframe" iframe-src="external.html"></div>

Directive :

angular.module('project.directives', [])
   .directive('externalIframe', ['$rootScope', function($rootScope) {
      return {
        restrict: 'C',
        replace: true,
        transclude: true,
        scope: {
          src: '@iframeSrc', // the src uses the data-binding from the parent scope
        },
        template: '<iframe src="{{src}}" height="100%" width="100%" frameborder="0"></iframe>',
        link: function(scope, elem, attrs) {
          //elem.src = "dummy.html"; // not working either
        }
      }
    }])

Problem : It fires 2 HTTP request (2 iframe loading). :

  • one to http://localhost:8000/app/{{src}} (iframe src not yet interpreated by angular)
  • one to http://localhost:8000/app/external.html (iframe src once interpreated by angular)

I want to avoid the useless first call.. How can I do that ?

I tried without src in the template and programmatically set it in the link or compile function but that doesn't fire the iframe loading.

edit: jsFiddle added for bug demo with compile method => you'll see in the network tab of firebug/chrome dev panel that two request are made :

  • http://fiddle.jshell.net/_display/%7B%7Bsrc%7D%7D
  • http://fiddle.jshell.net/_display/external.html

Thanks for the help

like image 429
Jscti Avatar asked Aug 21 '13 10:08

Jscti


3 Answers

You do not need a directive for this. Use ng-src on an actual iframe element. See the docs on ng-src.

<iframe ng-src="external.html"></iframe>
like image 192
markmarijnissen Avatar answered Oct 16 '22 12:10

markmarijnissen


Removing src from the iframe in the template and simply changing the attribute in the link function (via element.attr()) works:

return {
    restrict: 'E',
    require: '?ngModel',
    replace: true,
    transclude: true,
    template: '<iframe height="100%" width="100%" frameborder="0"></iframe>',
    link: function (scope, element, attrs) {
        element.attr('src', attrs.iframeSrc);
    }
};

Fiddle: http://jsfiddle.net/5rYrw/

like image 5
tdakhla Avatar answered Oct 16 '22 14:10

tdakhla


Instead of using 'link' use the 'compile' function, as you're essentially wanting to modify the HTML before insertion into the DOM. I think 'link' is inserted, and then bound to the scope.

So with link 1. compile is called with {{url}} - request by iframe is made 2. link is called, and {{url}} is replaced, hence you second call.

If you use 'compile' you can modify the src attribute yourself.

Give http://docs.angularjs.org/guide/directive a look over, hope this helps

Edit Check this fiddle http://jsfiddle.net/jbSx6/20/

return {
    restrict: 'E',
    require: '?ngModel',
    replace: true,
    transclude: true,
    template: '<iframe src="%url%" height="100%" width="100%" frameborder="0"></iframe>',
    compile: function (element, attrs, transclude) {
        console.log(element[0].outerHTML);
        element[0].outerHTML = element[0].outerHTML.replace('%url%',attrs.iframeSrc);
        console.log(element);
    }
};

<div ng-app="myApp">
   <div>display google in frame</div>
   <my-frame data-iframe-src="http://jsfiddle.net">test</my-frame>
</div>
like image 1
leon.io Avatar answered Oct 16 '22 13:10

leon.io