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

Chart does not resize inside shadow DOM (e.g. Polymer) #5763

Closed
makitama opened this issue Oct 10, 2018 · 14 comments · Fixed by #6556
Closed

Chart does not resize inside shadow DOM (e.g. Polymer) #5763

makitama opened this issue Oct 10, 2018 · 14 comments · Fixed by #6556

Comments

@makitama
Copy link

makitama commented Oct 10, 2018

Expected Behavior

The Bar Chart should resize when the window size is changed.

Current Behavior

The wrapper div does resize, but the Chart does not.

Steps to Reproduce (for bugs)

https://stackblitz.com/edit/polymer310-testcase-chartjs

import '../../../node_modules/chart.js/dist/Chart.js'

class BarChartElement extends PolymerElement {
  static get template() {
    return html`  
        <style include="shared-styles2">
        #content{
            height: 100%;
            width: 100%;
        }
        </style>
        <div id="content"></div>
      `;
  }
ready(){
super.ready();

        let iCan = document.createElement('canvas');
        iCan.id = 'temp';

        this.$.content.appendChild(iCan);

       setTimeout(function () {
           let ctx = (this.$.content.firstElementChild);
           this.chart = new Chart(ctx, {
               type: 'bar',
               data: {
                   datasets: [{
                       backgroundColor: color,
                       data: data,
                   }],
               },

               options: {
                   responsive: true,
                   maintainAspectRatio: true,
                   legend: {
                       display: false,
                   },
                   tooltips: {
                       enabled: false,
                   },
                   scales: {
                       xAxes: [{
                           scaleLabel: {
                               display: true,
                               labelString: 'Wochen',
                               fontSize: 16,
                           },
                           ticks:{
                               stepSize:1,
                               autoSkip: false,
                           },
                       }],
                       yAxes: [{
                           scaleLabel: {
                               display: true,
                               labelString: 'Auslastung in %',
                               fontSize: 16,
                           },
                       }]
                   }
               }
           });
       }.bind(this), 1);
    }
}
window.customElements.define('bar-chart', BarChartElement);

Environment

@benmccann
Copy link
Contributor

just fyi, you need triple backticks to escape multi-line code instead of just one backtick. I updated it for you

@simonbrunel
Copy link
Member

@Dreamergirly81 please provide a live test case (e.g. jsfiddle). It's complicated and time consuming for us to setup a polymer project to debug your project.

@makitama
Copy link
Author

@simonbrunel i added a test case to stackblitz, because jsfiddle and many others does not work with polymer 3! Hope you can see the Problem here:

https://stackblitz.com/edit/polymer310-testcase-chartjs

@simonbrunel
Copy link
Member

Thanks @Dreamergirly81, stackblitz is fine.

I'm not familiar with Polymer and it would require more investigation to find the cause of this issue but my first guess is that our responsive implementation doesn't currently support shadow DOM and thus is not able to detect when the canvas is attached to the DOM tree to insert the resize detector element.

@makitama
Copy link
Author

will chartjs support shadow dom in the future? It is a part of HTML 5 now and i think it should be supported in later versions. Or do you know if there is a easy fix/workaround for this?

@simonbrunel
Copy link
Member

I don't know any fix/workaround and I'm not even sure that's the issue. If shadow DOM is indeed not supported, we will be happy to review PR that fix this issue).

FYI, #5585 fixes a few things around that topic, included in v2.7.3

@etimberg
Copy link
Member

@Dreamergirly81 I had a look and it appears that the render-monitor CSS is injected in the wrong location. The method in the chart.js source that injects the CSS is injectCSS. The issue is that it puts the CSS in the document <head>. This poses a problem in the shadow DOM case as the shadow-root blocks the CSS style from above.

To test this theory I injected the CSS manually into the Polymer component in this test and resize works as expected.

In terms of long term solutions, I'm not sure what the best option is. What I can think of so far is:

  1. Walk up the DOM tree until we find either the <body> or a shadow-root and put the style under there
  2. Add the style inline instead of using a class (not sure if that causes a problem)

@makitama
Copy link
Author

@etimberg thank you! I was able to use your test case in my project, because we really need resizing of the charts. I never thought that CSS is causing this Problem...

@simonbrunel simonbrunel changed the title Chart does not resize inside polymer element Chart does not resize inside shadow DOM (e.g. Polymer) Dec 5, 2018
@jwillmer
Copy link

jwillmer commented Dec 5, 2018

I use window.addEventListener('resize', this.ChartInstance.resize(), true); in the meantime.

@etimberg
Copy link
Member

etimberg commented Dec 6, 2018

@jwillmer one caution on that is that it only fires if the whole page resizes, but it won't fire if the div containing the chart resizes.

@simonbrunel
Copy link
Member

  1. Walk up the DOM tree until we find either the or a shadow-root and put the style under there

It would require to detect when the node is attached to the DOM, which is exactly the purpose of the injected CSS.

  1. Add the style inline instead of using a class (not sure if that causes a problem)

I don't think @keyframes can be inlined.

@Dreamergirly81 @etimberg I'm not sure we will be able to correctly handle responsiveness within shadow DOM because we need to inject the CSS under all shadow roots and so we need to know when the canvas is added to the DOM in order to know the DOM scope.

@etimberg
Copy link
Member

@simonbrunel now that #6048 is merged, how do you feel about solving this with a documentation update? I think it's going to be hard to get the style auto-injected in the right spot, but with the external CSS file it's not hard to fix. See this example

@erikroe
Copy link

erikroe commented Sep 3, 2019

I would like to point out this issue still is present. I just tested it within a web component using LitElement and there is no resize done. It only works if I override the render root with using directly the light dom - rendering any advantages of web components useless.

@Simon-Tang
Copy link
Contributor

In the meantime, I was able to get the Chart to resize inside the Shadow DOM with this snippet:

this.shadow = this.attachShadow({ mode: 'open' });

const resizeStylesheet = document.createElement('link');
resizeStylesheet.setAttribute('href', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css');
resizeStylesheet.setAttribute('rel', 'stylesheet');

this.shadow.appendChild(resizeStylesheet);

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

Successfully merging a pull request may close this issue.

7 participants