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:
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.
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.
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.
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
You first need to check if the response is an arraybuffer, if it is, convert it to base 64. Also you can use setattribute to assign.