Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOMException: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed #2058

Closed
ravatsinh opened this issue Nov 4, 2019 · 21 comments · Fixed by #2785

Comments

@ravatsinh
Copy link

DOMException: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed

@vernvn
Copy link

vernvn commented Nov 6, 2019

i have the same problem; how to deal with it ?

@LucasManerich
Copy link

same problem using in angular 8 and ionic 4

@UniqueAlex
Copy link

UniqueAlex commented Dec 5, 2019

Same problem ionic4, how to solve it?

@sr-ricky
Copy link

I'm facing the same problem with ionic 5... Did someone find any solution?

@lanrene
Copy link

lanrene commented Dec 20, 2019

Interim plan from Yupeng in ionic4

  • index.html
<body>
  <div id="html2canvas"></div>
  <app-root></app-root>
</body>
  • xxx.ts
const element = document.getElementById('html2canvas');
const targetElement = document.getElementById('target').cloneNode(true);
element.appendChild(targetElement);
this.html2canvas.html2canvas(element.firstChild).then((img) => {
    this.img = img;
    element.firstChild.remove();
}).catch((res) => {
    console.log(res);
});
  • Html2canvasService.service.ts
import {Injectable} from '@angular/core';
import {AlertService} from './alert.service';

declare let html2canvas;

@Injectable()
export class Html2canvasService {
    constructor(private alert: AlertService) {

    }

    public html2canvas(ele) {

        if (!ele) {
            return;
        }

        const option = {allowTaint: true, useCORS: true};
        return html2canvas(ele, option).then((canvas) => {
            if (canvas) {
                return canvas.toDataURL('image/png');
            }
            return null;
        }).catch((res) => {
            console.log(res);
            return res;
        });
    }
}

@nuno
Copy link

nuno commented Dec 22, 2019

@G-yanpeng Can you please elaborate more your solution? Im trying do the same for ionic 4 angular8 version.

Thank you!

@abritopach
Copy link

Same problem. Did someone find any solution?

Thanks!

@lanrene
Copy link

lanrene commented Dec 24, 2019

@G-yanpeng Can you please elaborate more your solution? Im trying do the same for ionic 4 angular8 version.

Thank you!

angular8 有了新的变更,导致 html2canvas 不能正常工作。那么就有了这个临时解决方案,让 html2canvas 在 angular 之外工作,将需要生成图片的 dom 拷贝到 angular 入口(app-root)的同层来避免angular造成的影响。

Angular8 has new changes that cause html2canvas to not work properly. Then there is this temporary solution to make html2canvas work outside of angular, copy the dom that needs to generate the image to the same layer of the angular entry (app-root) to avoid the impact of angular.
-- by google translate

image

@ravimallya
Copy link

您能否提供xxx.ts组件文件的完整代码? 尝试导出到.pdf时,我们也遇到相同的错误。 除此错误外,其他一切都正常。 我也可以查看.pdf文件。
这是我的代码:
(Translated to Chinese using Google translator)
`
import { Component, OnInit } from '@angular/core';
import { WcExpenditureCalcPipe } from 'src/app/_pipes/wc-expenditure-calc.pipe';
// export to pdf
import { Router } from '@angular/router';
import { ExportAsService, ExportAsConfig } from 'ngx-export-as';
import { Platform } from '@ionic/angular';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { File } from '@ionic-native/file/ngx';
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer/ngx';

  @Component({
    selector: 'app-wc-estimate',
    templateUrl: './wc-estimate.page.html',
    styleUrls: ['./wc-estimate.page.scss'],
    providers: [WcExpenditureCalcPipe]
  })
  export class WcEstimatePage implements OnInit {
    dataEntered: any;
    wcEstimate: any;

    // export config
    storageDirectory: any;

    exportAsConfig: ExportAsConfig = {
      type: 'pdf', // the type you want to download
      elementId: 'myDiv', // the id of html/table element
      options: {
        margin: 15,
        jsPDF: {
          orientation: 'portrait',
          format: 'a4',
          unit: 'mm'
        },
        pdfCallbackFn: this.pdfCallbackFn // to add header and footer
      },
    }
    constructor(
      public router: Router,
      private exportAsService: ExportAsService,
      private transfer: FileTransfer,
      private file: File,
      private platform: Platform,
      private fileOpener: FileOpener,
      private wcExpenditureCalcPipe: WcExpenditureCalcPipe
    ) {
      this.platform.ready().then(() => {
        if (!this.platform.is('cordova')) {
          return false;
        }

        if (this.platform.is('ios')) {
          this.storageDirectory = this.file.externalDataDirectory;
        }
        else if (this.platform.is('android')) {
          this.storageDirectory = this.file.externalDataDirectory;
        }
        else {
          return false;
        }
      });
    }

    ngOnInit() {
      this.dataEntered = JSON.parse(localStorage.getItem('DataEntered'));
      this.getValues(this.dataEntered);
    }
    getValues(dataEntered: any) {
      this.wcEstimate = this.wcExpenditureCalcPipe.getWCE(dataEntered)
      console.log(this.wcEstimate);
    }

    // export PDF
    export(event) {
      const fileTransfer: FileTransferObject = this.transfer.create();

      this.exportAsService.get(this.exportAsConfig).subscribe((data: any) => {
        const fileName = 'PReport ' + this.dataEntered.Project_Name + ' - WC Estimate.pdf';
        fileTransfer.download(data, this.storageDirectory + fileName).then((entry) => {
          this.fileOpener.open(entry.toURL(), 'application/pdf').then(() => {
          }).catch(e => {
            console.log('Error opening file', e);
          });
        }, (error) => {
          console.log('error ' + JSON.stringify(error));
        });
      });
      event.preventDefault();
    }
    pdfCallbackFn(pdf: any) {
      // example to add page number as footer to every page of pdf
      const noOfPages = pdf.internal.getNumberOfPages();
      for (let i = 1; i <= noOfPages; i++) {
        pdf.setPage(i);
        pdf.text('WC Estimate', 15, 10)
        pdf.text('Page ' + i + ' of ' + noOfPages, 15, pdf.internal.pageSize.getHeight() - 10);
      }
    }

    //Edit report 
    editClick(event: any) {
      localStorage.setItem('isEdit', 'true');
      this.router.navigateByUrl('/dashboard/landing');

    }
    //done click 
    doneClick(event: any) {
      this.router.navigateByUrl('/dashboard/review');

    }
    // exit click 
    exitClick(event: any) {
      this.router.navigateByUrl('/dashboard/entry-point');
    }

  }

`
The platform.ready event is really not required. I was trying to add to 'Download' folder if it is android and 'Documents' folder if it is iOS.

@lanrene
Copy link

lanrene commented Jan 3, 2020

@ravimallya
I updated the content in html2canvasservice.service.ts, but I don't think it will help you. It should be noted that using this temporary scheme, images can be generated normally, but throw exception will still be reported.
Perhaps you can try PDF generation using JSPDF and html2canvas.

@kennethross
Copy link

Interim plan from Yupeng in ionic4

  • index.html
<body>
  <div id="html2canvas"></div>
  <app-root></app-root>
</body>
  • xxx.ts
const element = document.getElementById('html2canvas');
const targetElement = document.getElementById('target').cloneNode(true);
element.appendChild(targetElement);
this.html2canvas.html2canvas(element.firstChild).then((img) => {
    this.img = img;
    element.firstChild.remove();
}).catch((res) => {
    console.log(res);
});
  • Html2canvasService.service.ts
import {Injectable} from '@angular/core';
import {AlertService} from './alert.service';

declare let html2canvas;

@Injectable()
export class Html2canvasService {
    constructor(private alert: AlertService) {

    }

    public html2canvas(ele) {

        if (!ele) {
            return;
        }

        const option = {allowTaint: true, useCORS: true};
        return html2canvas(ele, option).then((canvas) => {
            if (canvas) {
                return canvas.toDataURL('image/png');
            }
            return null;
        }).catch((res) => {
            console.log(res);
            return res;
        });
    }
}

Thank you so much! Great workaround!

@derek90
Copy link

derek90 commented Jun 8, 2020

Interim plan from Yupeng in ionic4

  • index.html
<body>
  <div id="html2canvas"></div>
  <app-root></app-root>
</body>
  • xxx.ts
const element = document.getElementById('html2canvas');
const targetElement = document.getElementById('target').cloneNode(true);
element.appendChild(targetElement);
this.html2canvas.html2canvas(element.firstChild).then((img) => {
    this.img = img;
    element.firstChild.remove();
}).catch((res) => {
    console.log(res);
});
  • Html2canvasService.service.ts
import {Injectable} from '@angular/core';
import {AlertService} from './alert.service';

declare let html2canvas;

@Injectable()
export class Html2canvasService {
    constructor(private alert: AlertService) {

    }

    public html2canvas(ele) {

        if (!ele) {
            return;
        }

        const option = {allowTaint: true, useCORS: true};
        return html2canvas(ele, option).then((canvas) => {
            if (canvas) {
                return canvas.toDataURL('image/png');
            }
            return null;
        }).catch((res) => {
            console.log(res);
            return res;
        });
    }
}

I get the following error: "ERROR TypeError: html2canvas is not a function" in the following function call from the service:

return html2canvas(ele, option).then((canvas) => {
    if (canvas) {
        return canvas.toDataURL('image/png');
    }
    return null;
})

@venkatesanvaishali
Copy link

Interim plan from Yupeng in ionic4

  • index.html
<body>
  <div id="html2canvas"></div>
  <app-root></app-root>
</body>
  • xxx.ts
const element = document.getElementById('html2canvas');
const targetElement = document.getElementById('target').cloneNode(true);
element.appendChild(targetElement);
this.html2canvas.html2canvas(element.firstChild).then((img) => {
    this.img = img;
    element.firstChild.remove();
}).catch((res) => {
    console.log(res);
});
  • Html2canvasService.service.ts
import {Injectable} from '@angular/core';
import {AlertService} from './alert.service';

declare let html2canvas;

@Injectable()
export class Html2canvasService {
    constructor(private alert: AlertService) {

    }

    public html2canvas(ele) {

        if (!ele) {
            return;
        }

        const option = {allowTaint: true, useCORS: true};
        return html2canvas(ele, option).then((canvas) => {
            if (canvas) {
                return canvas.toDataURL('image/png');
            }
            return null;
        }).catch((res) => {
            console.log(res);
            return res;
        });
    }
}

This works vey well. Thank you so much for the solution. With ionic native elements(like ion-text, ion-icon inside the element to copy) this is not working. But i changed my ionic elements to html. Now it is working perfect.

@fromage9747
Copy link

welp... 2021 and this issue is still present. The above workaround doesn't work for me. I still get the same error.

@Hanzofm
Copy link

Hanzofm commented May 5, 2021

Same problem here :(

@coloz
Copy link

coloz commented May 6, 2021

angular9,Same problem is still present.

@dluigirafael
Copy link

Ionic React, same problem.
Screenshot from 2021-05-17 08-58-12

@fromage9747
Copy link

What solved it for me was using dom-to-image-improved https://www.npmjs.com/package/dom-to-image-improved
`import domToImage from 'dom-to-image-improved';
const result = await domToImage.toPng(this.printableArea, domToImageOptions);

if (result) {
const doc = new jspdf.jsPDF('p', 'mm', 'a4');
doc.addImage(result, 'PNG', 20, 20, 290, 260);
const pdfOutput = doc.output();
const buffer = new ArrayBuffer(pdfOutput.length);
const array = new Uint8Array(buffer);
for (let i = 0; i < pdfOutput.length; i++) {
array[i] = pdfOutput.charCodeAt(i);
}
}`

Can't for the life of me get the code block to work...

@torrobinson
Copy link

For anyone arriving here via Google looking for a solution, @ibrahimAboelsuod's fork contains a built version of a fix here.

I was able to swap out the built .min.js file and it resolved my issues.

@AntoscencoVladimir
Copy link

@lanrene thank you

@BO-DI
Copy link

BO-DI commented Sep 26, 2023

i also have a sample problem.
for example:
1/function page
image
2/code page
image
image
image

3/problem page
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.