Search code examples
google-visualizationpolymeryeomanweb-componenthtml-imports

How to render <google-chart> web component in Polymer


NOTE: UPDATES (including solution) to this question at the end...

I can't get a <google-chart> element to render on my page.

I used Yeoman's Polymer generator to scaffold a Polymer project. I have added some custom elements and also imported and instantiated Iron and Paper elements from the Polymer Catalog. I am using the standard procedure to do this:

  1. bower install --save [[polymerElement]], then
  2. <link rel="import" href="../bower.../[[element]].html"> in elements.html.

Following the <google-chart> instructions in the Google Web Components catalog section, I have tried to render their example pie chart on my page. Although the element isn't rendering correctly, there are no errors in the console, there is a gap in the page content for the element, and the markup all appears in my inspector, with 2 exceptions:

  1. The rendered HTML does not include a "rows" attribute, which I cannot seem to fix.
  2. The inner content of the <google-chart> component is rather sparse, with just 3 children elements:
    • <iron-ajax>
    • <div>
    • <google-legacy-loader>

Here is the relevant code:

elements.html:

<!-- Iron elements -->
<link rel="import" href="../bower_components/iron-component-page/iron-component-page.html">
<link rel="import" href="../bower_components/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/iron-icons/maps-icons.html">
<link rel="import" href="../bower_components/iron-icons/social-icons.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../bower_components/iron-selector/iron-selector.html">

<!-- Paper elements -->
<link rel="import" href="../bower_components/paper-drawer-panel/paper-drawer-panel.html">
<link rel="import" href="../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/paper-item/paper-item.html">
<link rel="import" href="../bower_components/paper-material/paper-material.html">
<link rel="import" href="../bower_components/paper-menu/paper-menu.html">
<link rel="import" href="../bower_components/paper-scroll-header-panel/paper-scroll-header-panel.html">
<link rel="import" href="../bower_components/paper-styles/paper-styles-classes.html">
<link rel="import" href="../bower_components/paper-toast/paper-toast.html">
<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html">

<!-- 3rd Party Components -->
<link rel="import" href="../bower_components/google-apis/google-apis.html">
<link rel="import" href="../bower_components/google-apis/google-js-api.html">
<link rel="import" href="../bower_components/google-chart/google-chart.html">

<!-- etc... -->

index.html:

<section data-route="dashboard">
    <h2 class="page-title">Data Dashboard</h2>
    <p>This is the dashboard section</p>
    <p>This is a 'google-chart' object:</p>
    <google-chart type='pie' options='{"title": "Distribution of days in 2001Q1"}' rows='[["Jan", 31], ["Feb", 28], ["Mar", 31]]' cols='[{"label":"Month", "type":"string"}, {"label":"Days", "type":"number"}]'></google-chart>

    <p>You can get more info here:</p>
    <a href="https://elements.polymer-project.org/elements/google-chart">https://elements.polymer-project.org/elements/google-chart</a>
</section>
<!-- etc... -->

UPDATE:

As Supersharp stated, this <google-charts> code loads in a single page environment.

As far as loading in the Yeoman-scaffolded Polymer environment I'm working in, after further testing it seems that the <google-chart> object will load in the main app/index.html file as long as it is not in the <template> tag:

<!doctype html>
<html lang="">

<head>
    ...
    <!-- build:css styles/main.css -->
    <link rel="stylesheet" href="styles/main.css">
    <!-- endbuild-->

    <!-- build:js bower_components/webcomponentsjs/webcomponents-lite.min.js -->
    <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
    <!-- endbuild -->

    <!-- will be replaced with elements/elements.vulcanized.html -->
    <link rel="import" href="elements/elements.html">
    <!-- endreplace-->

    <!-- For shared styles, shared-styles.html import in elements.html -->
    <style is="custom-style" include="shared-styles"></style>
</head>

<body unresolved class="fullbleed layout vertical">
    <span id="browser-sync-binding"></span>

NOTE: google-chart will load here...

    <template is="dom-bind" id="app">

NOTE: google-chart WON'T load here or in any of the elements below...

        <paper-drawer-panel id="paperDrawerPanel">
            <!-- Drawer Scroll Header Panel -->
            <paper-scroll-header-panel drawer>
                <!-- Drawer Toolbar -->
                <paper-toolbar id="drawerToolbar"> ... </paper-toolbar>
                <!-- Nav Menu Section Title -->
                <paper-item class="menu-section-title"> ... </paper-item>
                <!-- Drawer Section Content -->
                <paper-menu class="list" attr-for-selected="data-route" selected="[[route]]"> ... </paper-menu>
            </paper-scroll-header-panel>
            <!-- Main Area -->
            <paper-scroll-header-panel main condenses keep-condensed-header>
                <!-- Main Toolbar -->
                <paper-toolbar id="mainToolbar" class="tall" alt-class="medium-tall"> ... </paper-toolbar>
                <!-- Main Content -->
                <div class="content"> ... </div>
            </paper-scroll-header-panel>
        </paper-drawer-panel>
    </template>

NOTE: google-chart will load here...

    <!-- build:js scripts/app.js -->
    <script src="scripts/userData.js"></script>
    <script src="scripts/app.js"></script>
    <!-- endbuild-->
</body>
</html>

However, I need the <google-charts> component loaded in that <template> block (where all the rest of the content is).

Can anyone explain why this won't load in the <template> block?

Can anyone further explain how I can get this element to render wherever I want it in the app?

Thank you all so much in advance.


SOLUTION:

Using the Registration and Lifecycle Callbacks I have successfully rendered this in a template with the following method:

First, add a queryable element into the <template> element to serve as a container:

<p>This is a 'google-chart' object:</p>
<figure id="chart-container"></figure>

Second, inside the Polymer() constructor, create the <google-chart> element and attach it to the container as part of the attached lifecycle event:

attached: function() {
  // create an instance with createElement:
  var chartContainer = document.querySelector('figure#chart-container');

  var pieChartAttributes = {
    'id': 'pie-chart',
    'type': 'pie',
    'options': '{"title": "Distribution of days in 2001Q1"}',
    'rows': '[["Jan", 31], ["Feb", 28], ["Mar", 31]]',
    'cols': '[{"label":"Month", "type":"string"}, {"label":"Days", "type":"number"}]',
  };

  var pieChart = document.createElement('google-chart');

  for (var key in pieChartAttributes) {
    pieChart.setAttribute(key, pieChartAttributes[key]);
  }

  chartContainer.appendChild(pieChart);
} // end attached()

While there is a slight delay in the element rendering on-screen, this is a working solution.


Solution

  • I've copy-pasted your code and in a single file and it worked:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <link rel="import" href="/scripts/components/google-chart/google-chart.html">
    </head>
    <body>
        <section data-route="dashboard">
            <h2 class="page-title">Data Dashboard</h2>
            <p>This is the dashboard section</p>
            <p>This is a 'google-chart' object:</p>
            <google-chart type='pie' options='{"title": "Distribution of days in 2001Q1"}' rows='[["Jan", 31], ["Feb", 28], ["Mar", 31]]' cols='[{"label":"Month", "type":"string"}, {"label":"Days", "type":"number"}]'></google-chart>
    
            <p>You can get more info here:</p>
            <a href="https://elements.polymer-project.org/elements/google-chart">https://elements.polymer-project.org/elements/google-chart</a>
        </section>
    </body>
    </html>
    

    NB: Only the custom element you explicitely use (ie google-chart) should be imported as a <link>.

    UPDATE

    <template> content is never rendered. It's the main purpose of that type of element. You'll have to copy its content to another element (not a template!) in the main document to make it visible. The other nested elements won't render more. Example here.