Seems to be a race-condition type of bug, if I close the pdf viewer too quickly. (or change [zoom])
I get this with ng2-pdf-viewer v5.1.1 (angular 5.2) in Chrome if I close (set *ngIf=false the parent's div) too quickly before the PDF is totally loaded... I have a "close" button that kills the pdfviewer parent div. To guard it, to only be able to close when the PDF is loaded, I am catching the (after-load-complete) and (page-rendered), not allowing to set the pdfviewer parent div's ngIf to false unless those have completed, but still getting the crash/exception.
TypeError: Cannot read property 'div' of undefined
at backtrackBeforeAllVisibleElements (VM474151 pdf_viewer.js:558)
at getVisibleElements (VM474151 pdf_viewer.js:605)
at PDFViewer._getVisiblePages (VM474151 pdf_viewer.js:5400)
at PDFViewer.forceRendering (VM474151 pdf_viewer.js:5080)
at PDFRenderingQueue.renderHighestPriority (VM474151 pdf_viewer.js:4191)
at continueRendering (VM474151 pdf_viewer.js:4256)
at ZoneDelegate.invoke (VM472116 zone.js:388)
offending line of code is here in pdf_viewer.js:558:
function backtrackBeforeAllVisibleElements(index, views, top) {
if (index < 2) {
return index;
}
var elt = views[index].div; <----- HERE pdf_viewer.js:558
where index == 3 for my 3-page pdf (out of bounds!).
The html template:
<div *ngIf='showing' (click)="close()">
<div (click)="$event.stopPropagation()">
<pdf-viewer
[src]='content_url'
[zoom]='pdfzoom'
[original-size]="false"
[render-text]="true"
[autoresize]="true"
[show-all]="true"
[fit-to-page]="false"
(after-load-complete)="onPdfLoad($event)"
(error)="onPdfError($event)"
(on-progress)="onPdfProgress($event)"
(page-rendered)="onPdfRendered($event)"
></pdf-viewer>
</div>
</div>
the component.ts
close() {
if (this.can_close) this.showing = false;
}
onPdfLoad(e) {
this.can_close = true;
}
zoomIn() {
if (this.can_close) {
this.pdfzoom = Math.min( this.pdfzoom_max, this.pdfzoom+0.1 );
}
}
zoomOut() {
if (this.can_close) {
this.pdfzoom = Math.max( this.pdfzoom_min, this.pdfzoom-0.1 );
}
}
I get this also when changing the [zoom] parameter...
Hey so I had the same issue. I noticed that if you added a bounds check for index it fixes the issue. The problem is actually with another package that ng2-pdf-viewer depends on.
Line 555: pdf_viewer.js
function backtrackBeforeAllVisibleElements(index, views, top) {
if (index < 2 || views.length <= index) {
return index;
}
console.log('index: ', index, 'view length: ', views.length);
var elt = views[index].div;
So I am pretty sure that ng2-pdf-viewer has to run this check before calling
backtrackBeforeAllVisibleElements
Just confirmed this fixes the issue for us. I can bang on the [zoom], and I can *ngIf=false the parent div around the <pdf-viewer> without crashes now. Seems to make it rock solid for us!
Looks like we'll need one of two fixes:
node_modules/pdfjs-dist/web/pdf_viewer.js with @jaronwright 's above changeng2-pdf-viewer to not feed data to pdfjs-dist/web/pdf_viewer.js that exceeds these bounds (I dont know if this is possible).Looks like it's # 2, ng2-pdf-viewer needs to fix the way it uses pds.js, see here:
https://github.com/mozilla/pdf.js/pull/9895#issuecomment-405515206
To quote:
...looking (quickly) at the implementation of https://github.com/vadimdez/ng2-pdf-viewer/,
in particular the following file https://github.com/VadimDez/ng2-pdf-viewer/blob/master/src/app/pdf-viewer/pdf-viewer.component.ts,
does highlight a number of questionable practices.
Note that it creates a PDFViewer instance, which is totally fine (and expected behaviour);
see https://github.com/VadimDez/ng2-pdf-viewer/blob/c14aca86148d20656765531cc01a955f55915458/src/app/pdf-viewer/pdf-viewer.component.ts#L210
What's not, at all, expected however is that the renderPage method is then
manually clearing out the DOM;
see https://github.com/VadimDez/ng2-pdf-viewer/blob/c14aca86148d20656765531cc01a955f55915458/src/app/pdf-viewer/pdf-viewer.component.ts#L389
before manually creating PDFPageView instances at
https://github.com/VadimDez/ng2-pdf-viewer/blob/c14aca86148d20656765531cc01a955f55915458/src/app/pdf-viewer/pdf-viewer.component.ts#L409
for rendering.
The whole point of using PDFViewer, rather than PDFPageView directly, is that the
viewer provides abstractions for a lot of the operations (such as initializing
the necessary PDFPageView instances, and controlling/triggering rendering).
However, this mixing of PDFViewer and PDFPageView usage is not intended
behaviour and is thus explicitly unsupported (from the PDF.js library point of view).
To summarize: The way that the https://github.com/VadimDez/ng2-pdf-viewer
project is using the PDF.js library appears to be incorrect, which is a bug that
should be reported to that project instead.
and:
Anyway, as explained above, the problem (but not the only one) is that
https://github.com/vadimdez/ng2-pdf-viewer/ is manually clearing out the DOM.
Essentially it's "pulling the rug from under the feet" of the getVisibleElements
function; thus outright failing, rather than swallowing the error, seem appropriate here.
In the meantime, I have to wrap timers around my close and zoom buttons, to prevent the user from changing them too fast:
Here I guard the close pdf button with can_close, and I buffer the update of the pdfzoom (directly drives the <pdfviewer>'s [zoom]) with a 2ndary variable pdfzoom_now (to allow users to quickly set zoom by hammering on the zoom buttons).
// takes some time for the PDF to destroy/load the DOM - if change too quickly, browser can crash
can_close:boolean = false;
guardzoom:boolean = false;
zoomUpdate( timeout ) {
if (this.guardzoom || !this.can_close) {
// ignore update, it'll get picked up at the end of the current running setTimeout
} else {
// update immediately
this.pdfzoom = this.pdfzoom_now;
// guard for a second. if another change came in while guarding, kick off another update
this.guardzoom = true;
this.can_close = false;
setTimeout( () => {
this.guardzoom = false;
this.can_close = true;
if (this.pdfzoom != this.pdfzoom_now)
this.zoomUpdate( timeout );
}, timeout );
}
}
zoomIn() {
this.pdfzoom_now = Math.min( this.pdfzoom_max, this.pdfzoom_now+0.1 );
this.zoomUpdate( 1000 );
}
zoomOut() {
this.pdfzoom_now = Math.max( this.pdfzoom_min, this.pdfzoom_now-0.1 );
this.zoomUpdate( 1000 );
}
onPdfLoad() {
// takes some time for the PDF to load - if close too early browser can crash
setTimeout( () => {
this.can_close = true;
if (this.pdfzoom != this.pdfzoom_now)
this.zoomUpdate( 1000 );
}, 3500 );
console.log( "loaded" );
}
close() {
// protect against closing the pdf viewer while it's loading (which can cause a crash)
if (this.can_close)
this.showing = false;
};
The question I have, is then:
ng2-pdf-viewer without running into all kinds of these pdf.js crashes? Follow on question:
ng2-pdf-viewer wrong somehow? Feels like my simple [zoom] increment/decrementer can't possibly be abusing the system.... It's so simple... like it's exposing an internal bug of ng2-pdf-viewer.I see that the demo page doesn't have the bug when changing zoom: https://vadimdez.github.io/ng2-pdf-viewer/ even with my own .pdf loaded into the demo.
My package.json is in the standalone demo, as you can see I am using angular 5.2 and angular-cli 1.7.1
Very Simple Demo which reproduces, using vadimdez's pdf:
See here for a minimal, self contained, Angular 5.2.0 app: https://github.com/subatomicglue/ng2pdfViewerTest
The code added is thus:
Added to app.component.html:
<div (click)="pdfshow = !pdfshow">close</div>
<div (click)="pdfzoom=1 < (pdfzoom+0.1) ? 1 : (pdfzoom+0.1)">zoomin</div>
<div (click)="pdfzoom=(pdfzoom-0.1) < 0.1 ? 0.1 : (pdfzoom-0.1)">zoomout</div>
<div *ngIf='pdfshow'>
viewer:
<pdf-viewer *ngIf="pdfshow" (click)="$event.stopPropagation()" style='background-color:black;display: block;'
[src]="'https://vadimdez.github.io/ng2-pdf-viewer/assets/pdf-test.pdf'"
[original-size]="false"
[render-text]="true"
[autoresize]="true"
[show-all]="true"
[zoom]="pdfzoom"
[fit-to-page]="false"
></pdf-viewer>
</div>
Added to app.component.ts:
pdfshow:boolean = true;
pdfzoom:number = 0.8;
If I hit close too quick, or hit zoomin/zoomout too quick, I'll get the same crash as above.
I also encountered this bug @subatomicglue . I attempted a similar solution to yours. (guarding zoom/close with a loading flag)
In my case I solved the problem by only setting the loaded flag once _all_ pages have rendered. (See below example)
It would be great if the lib could maybe emit an additional (after-render-complete) event or something.
I know this still remains a less-than-optimal workaround but perhaps it helps you :)
Container component class:
export class PdfViewerComponent {
// ...
loaded = false;
showPdf = true;
pageCount: number;
pagesRendered = 0;
pdfLoaded = event => {
this.pageCount = event.pdfInfo.numPages;
};
pageRendered = () => {
this.pagesRendered += 1;
if (this.pagesRendered === this.pageCount) {
this.renderComplete();
}
};
renderComplete = () => {
this.loaded = true;
}
close = () => {
if (this.loaded) {
this.showPdf = false;
}
}
// ...
}
Container component template:
<div *ngIf="showPdf">
<pdf-viewer [src]="pdfSrcConfig"
[autoresize]="true"
[original-size]="false"
(page-rendered)="pageRendered($event)"
(after-load-complete)="pdfLoaded($event)"
></pdf-viewer>
</div>
Super smart. Love it. (Hate that I have to do this). But you found a solid solution. Thanks for sharing!
error when closing large pdf too early.. any help?
If I wrap the zoom with the isLoaded flag, it still show the error. Any ideas?
Same problem, I wrap the zoom in isLoaded flag but still show the error. any Ideas?
Can you paste some examples of your code?
I have the same error when changing the route before finishing the render of all pages (i.e closing the pdf to quickly)
Any updates?
Actually I can't reproduce the problem in the example while zooming.
But using the change in pdf_viewer.js solves my problem.
I'll keep investigating
This is my nasty solution:
After the offered workarounds didn't work for me, I focused on patching pdfjs-dist like @jaronwright mentioned.
npm with yarn in order to manage descendant dependencies more easily. "resolutions": {
"ng2-pdf-viewer/pdfjs-dist": "git+https://[email protected]/noamyg/pdfjs-dist.git"
}
Now ng2-pdf-viewer has no node_modules and pdfjs-dist resolved to a patched version, fixing all of the issues described in this page and in #224
Hoping anyone would find this solution helpful despite its' hacky nature...
@ColinT @noamyg
I tried, but it did not work

ngOnInit() {
this.pdfNo = 13;
}
<div style="max-height: 200px; max-width: 500px; position: relative; overflow: auto">
<pdf-viewer style="display: block" *ngIf="pdfSrc" [autoresize]="true" [(page)]="pdfNo" class="pdf-viewer"
[original-size]="false" [show-all]="true" [src]="pdfSrc" [render-text]="false" [stick-to-page]="true">
</pdf-viewer>
</div>
still got, 13 out of bounds
version 5.2.3

also used
"resolutions": {
"ng2-pdf-viewer/pdfjs-dist": "git+https://[email protected]/noamyg/pdfjs-dist.git"
}
and also got 'div' of undefined (not setting the pdfNo in ngInit)
@jiangyh1024 delete your package-lock.json and node_modules folder in your root project directory, then run yarn install and try again
@noamyg tried, still did not work

is it related to the version of pdfjs-dist ?
I had the same error and I fixed it with following changes.
var elt = views[index].div; It is inside 'backtrackBeforeAllVisibleElements' function.var elt = views[index-1].div; and save.Hey so I had the same issue. I noticed that if you added a bounds check for index it fixes the issue. The problem is actually with another package that ng2-pdf-viewer depends on.
Line 555: pdf_viewer.js
function backtrackBeforeAllVisibleElements(index, views, top) { if (index < 2 || views.length <= index) { return index; } console.log('index: ', index, 'view length: ', views.length); var elt = views[index].div;So I am pretty sure that ng2-pdf-viewer has to run this check before calling
backtrackBeforeAllVisibleElements
That fixed the issue for me. So strange though coz I still don't understand the check for index!
This is a big problem for a lot of people, and it has thus far received no apparent attention from the author. We have it from the authors of pdf_viewer.js that ng2-pdf-viewer is using the library incorrectly.
@VadimDez, with all due respect, are you looking at your issue tracker? Would you please chime in here and give us some help? People are having to use some pretty cruddy workarounds to get around this.
my fix for now, global error handler ignores this error when i close material dialog:
@Injectable()
export class MyErrorHandler implements ErrorHandler {
//https://medium.com/@amcdnl/global-error-handling-with-angular2-6b992bdfb59c
constructor(
private injector: Injector
) {
}
handleError(error: any) {
console.error(error);
if (error.message.startsWith(`Uncaught (in promise): TypeError: Cannot read property 'div' of undefined
TypeError: Cannot read property 'div' of undefined
at backtrackBeforeAllVisibleElements`)) {
// https://github.com/VadimDez/ng2-pdf-viewer/issues/367
console.log('ignoring error');
return;
}
setTimeout(() => {
const errorService: ErrorService = this.injector.get(ErrorService);
errorService.genericError();
},1);
}
}
Looks like issue was fixed
Does this error still occur with version >5.3.1 ?
Hey guys, im using this with a ionic v4 app and if use the zoom prop and try do drag to another page the app crashes, no erros are shown in the console. Any suggestions are welcome.
Version:
"ng2-pdf-viewer": "^6.1.2",
Unfortunately, I did not find any solutions yet. However, I replaced it with webview instead. So when users want to read a PDF take them to a webview instead, it work perfectly.
Unfortunately, I did not find any solutions yet. However, I replaced it with webview instead. So when users want to read a PDF take them to a webview instead, it work perfectly.
Yeah, i have already tried 3 pdf libs out, all crashes when zooming. The webview is displayed inside the app or it open another page?
You can open it in the app if you specific the target to be equal to _self
and _system if you want to open in the device browser
checkout this
https://github.com/apache/cordova-plugin-inappbrowser
Most helpful comment
The question I have, is then:
ng2-pdf-viewerwithout running into all kinds of thesepdf.jscrashes?Follow on question:
ng2-pdf-viewerwrong somehow? Feels like my simple[zoom]increment/decrementer can't possibly be abusing the system.... It's so simple... like it's exposing an internal bug ofng2-pdf-viewer.