19

I have a scope like $scope.doc_details in my angularjs controller, and I want to use it to display a pdf file by using a tag, like this:

<object data="{{doc_details.file_url}}" type="application/pdf"></object>

but it doesn't get loaded in the browser, in my chrome console, all I see is:

Failed to load resource: the server responded with a status of 404 (Not Found) 
http://localhost/%7B%7Bdoc_details.file_url%7D%7D

and when I just display it using <span>{{doc_details.file_url}}</span> it show the value.

2
  • 2
    I bet the object is evaluating the string before angular has a chance to replace it with the final data. Commented Feb 15, 2013 at 21:02
  • any workaround for this? Commented Feb 15, 2013 at 21:13

4 Answers 4

35

As of AngularJS 1.1.4, you can use the ng-attr- prefix for the data attribute:

<object ng-attr-data="{{doc_details.file_url}}" type="application/pdf"></object>

See the ngAttr for binding to arbitrary attributes section on AngularJS: Interpolation and data-binding.

Sign up to request clarification or add additional context in comments.

4 Comments

This will not work with IE. IE will not let you change the data attribute after it has been loaded. You'll likely get a message box saying that access is denied. You should load it via a directive instead to delay the binding.
is that still the case now? I can't seem to easily google "object html element angularjs" i get a bunch of results about passing software objects and not html element objects. I'm getting strange issues with my code. Any updated answer to this or a link to docs will help thanks :)
This is still the case with IE 11.
Noting that I've not had any success with this method on AngularJS 1.7.
25

The problem here is that the browser is seeing

<object data="{{doc_details.file_url}}" type="application/pdf"></object>

in the DOM before Angular compiles it, and obviously {{doc_details.file_url}} isn't a valid URL.

Directives can be your friend here.

Say we want to write:

<pdf src='doc_details.file_url'></pdf>

We can create a directive:

app.directive('pdf', function() {
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            var url = scope.$eval(attrs.src);
            element.replaceWith('<object type="application/pdf" data="' + url + '"></object>');
        }
    };
});

This will defer the creation of the object element until we actually have the URL available to us from the scope (assuming it's already there - otherwise you'd want to $watch the src attribute on the scope until it became available).

Here this is in a fiddle.

2 Comments

Ran into this problem while using angular2. Any thoughts on how to use data-binding with <object> tag?
@satchmorun Finally this was the solution that worked for me. Indeed delaying the binding was the trick. Thanks!
1

Thank you satchmorun, but if smb want change link without reloading page or modal you can use:

<pdf2 src="pdfUrl" height="heightForPDF"></pdf2>

And this directive:

app.directive('pdf2', ['$compile', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            src: "=",
            height: "="
        },
        link: function (scope, element, attr) {
            function update(url) {
                    element.html('<object data="' + url + '" type="application/pdf" width="100%" style="height: ' + scope.height + 'px">' +
                        'Для просмотра pdf:<br /> Для Internet Explorer установите <a target="_blank" href="http://get.adobe.com/reader/">Acrobat Reader</a><br />' +
                        'Для Chrome: <a target="_blank" href="https://support.google.com/chrome/answer/6213030?hl=ru">Проверьте настройки</a>' +
                        '</object>');
                    $compile(element.contents())(scope);
            }
            scope.$watch('src', update);
        }
    };
}]);

Thank you Jerry from this answer and example of recompile a dynamically loaded directive.

p.s. "pdfUrl" and "heightForPDF" are variable in scope

Comments

0

The browser tries to process the thing before AngularJS replaced the angulary expression with something the browser can work with, causing an error.

Adding an ng-cloak fixes the issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.