Jon
Jon

Reputation: 3184

Using an external Angular element with Polymer

I'm teaching myself how to use Polymer [1.0], and I'm attempting to implement a data grid. Problem is...Polymer doesn't have a data grid as a base iron/paper/core element, so I've had to go out and find one.

Luckily, there's a nice one that follows the Google Material Design design specifications, so my intention is to use this one!

My page is set up so that there is a left page drawer, a top header, and a content section. I want the data grid to go into this content section.

The problem I'm facing is that it doesn't appear that the DOM is rendering the data grid component table. It's like it's not running those scripts and filling in the Angular data. My inkling is that it has to do with the way Polymer elements are self-contained, so the data grid scripts aren't reaching it.

I have successfully run this Codepen locally by putting the HTML into a test.html file, and adding the JS to a <script> tag at the bottom of the test HTML page. Everything renders fine. When I try copying and pasting into my application, something happens and the grid won't render.

My index.html code is below:

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

<head>
  <meta charset="utf-8">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="generator" content="Project Emerald" />
  <title>Data Grid</title>

  <!-- 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.min.js"></script>
  <!-- endbuild -->

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

  <!-- Custom SCSS Styles -->
  <link rel="stylesheet" href="styles/scss/styles.css">

  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.10.1/angular-material.min.css">
  <link rel="stylesheet" href="http://rawgit.com/daniel-nagy/md-data-table/master/dist/md-data-table.css">

</head>

<body unresolved class="fullbleed layout vertical">

  <paper-drawer-panel id="paperDrawerPanel">
    <!-- Drawer Scroll Header Panel -->
    <paper-scroll-header-panel drawer fixed>

      <!-- Drawer Toolbar -->
      <paper-toolbar id="drawerToolbar">
        <img src="images/dark-green.svg" class="app-logo" />
      </paper-toolbar>

      <!-- Drawer Content -->
      <paper-menu class="list" attr-for-selected="data-route" selected="[[route]]">
        <a data-route="inbox" href="#">
          <iron-icon icon="inbox"></iron-icon>
          <span>Inbox</span>
        </a>
        <a data-route="outbox" href="#">
          <iron-icon icon="send"></iron-icon>
          <span>Outbox</span>
        </a>
        <a data-route="trash" href="#">
          <iron-icon icon="delete"></iron-icon>
          <span>Trash</span>
        </a>
        <a data-route="spam" href="#">
          <iron-icon icon="report"></iron-icon>
          <span>Spam</span>
        </a>
        <paper-submenu>
          <div class="menu-trigger">
            <a data-route="forum" href="#">
              <iron-icon icon="question-answer"></iron-icon>
              <span>Forums</span>
            </a>
          </div>
          <paper-menu class="menu-content">
            <paper-item>General</paper-item>
            <paper-item>UI/UX</paper-item>
            <paper-item>Frontend Dev</paper-item>
            <paper-item>Graphic Design</paper-item>
            <paper-item>Photography</paper-item>
          </paper-menu>
        </paper-submenu>
        <a data-route="updates" href="#">
          <iron-icon icon="flag"></iron-icon>
          <span>Updates</span>
        </a>
        <a data-route="promos" href="#">
          <iron-icon icon="card-membership"></iron-icon>
          <span>Promos</span>
        </a>
      </paper-menu>

    </paper-scroll-header-panel>

    <!-- Main Area -->
    <paper-scroll-header-panel main fixed>

      <!-- Main Toolbar -->
      <paper-toolbar id="mainToolbar">
        <paper-icon-button id="paperToggle" icon="menu" paper-drawer-toggle></paper-icon-button>

        <!-- Application name -->
        <div class="top top-container center horizontal layout flex">
          <div class="title">Grid Title</div>
        </div>

        <!-- Toolbar icons -->
        <paper-icon-button icon="filter-list"></paper-icon-button>
        <paper-icon-button icon="search"></paper-icon-button>
      </paper-toolbar>

      <!-- Main Content -->
      <div class="content cards layout">

        <md-content layout="column" flex>
          <md-card ng-controller="nutritionController">
            <md-data-table-toolbar ng-show="!selected.length">
              <h2 class="md-title">Nutrition</h2>
            </md-data-table-toolbar>

            <md-data-table-toolbar class="alternate" ng-show="selected.length">
              <div>{{selected.length}} {{selected.length > 1 ? 'items' : 'item'}} selected</div>
            </md-data-table-toolbar>

            <md-data-table-container>
              <table md-data-table class="md-primary" md-row-select="selected" md-progress="deferred">
                <thead md-order="query.order" md-trigger="onorderchange">
                  <tr>
                    <th order-by="name" name="Dessert" unit="100g serving"></th>
                    <th order-by="type" name="Type"></th>
                    <th numeric order-by="calories.value" name="Calories"></th>
                    <th numeric unit="g" order-by="fat.value" name="Fat"></th>
                    <th numeric unit="g" order-by="carbs.value" name="Carbs"></th>
                    <th numeric unit="g" order-by="protein.value" name="Protein"></th>
                    <th numeric unit="mg" order-by="sodium.value" name="Sodium"></th>
                    <th numeric unit="%" order-by="calcium.value" name="Calcium"></th>
                    <th numeric unit="%" order-by="iron.value" name="Iron"></th>
                  </tr>
                </thead>
                <tbody>
                  <tr md-auto-select md-disable-select="dessert.name === 'Jelly bean'" ng-repeat="dessert in desserts.data | orderBy: query.order | limitTo: query.limit: (query.page - 1) * query.limit">
                    <td>{{dessert.name}}</td>
                    <td>
                      <md-select ng-model="dessert.type" placeholder="Other">
                        <md-option ng-value="type" ng-repeat="type in getTypes()">{{type}}</md-option>
                      </md-select>
                    </td>
                    <td>{{dessert.calories.value}}</td>
                    <td>{{dessert.fat.value | number: 2}}</td>
                    <td>{{dessert.carbs.value}}</td>
                    <td>{{dessert.protein.value | number: 2}}</td>
                    <td>{{dessert.sodium.value}}</td>
                    <td show-unit>{{dessert.calcium.value}}</td>
                    <td show-unit>{{dessert.iron.value}}</td>
                  </tr>
                </tbody>
              </table>
            </md-data-table-container>

            <md-data-table-pagination md-limit="query.limit" md-page="query.page" md-total="{{desserts.count}}" md-trigger="onpagechange"></md-data-table-pagination>
          </md-card>
        </md-content>

      </div>
    </paper-scroll-header-panel>
  </paper-drawer-panel>

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

  <!-- Core jQuery -->
  <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

  <!-- Data table libraries -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-aria.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.10.1/angular-material.min.js"></script>
  <script src="http://rawgit.com/daniel-nagy/md-data-table/master/dist/md-data-table.js"></script>

  <script src="bower_components/md-data-table/dist/sample.js"></script>

</body>

</html>

Code for sample.js:

angular.module('demoApp', ['ngMaterial', 'md.data.table'])

.controller('nutritionController', ['$q', '$scope', '$timeout', function ($q, $scope, $timeout) {

  $scope.selected = [];

  $scope.query = {
    order: 'name',
    limit: 5,
    page: 1
  };

  $scope.desserts = {
    "count": 9,
    "data": [
      {
        "name": "Frozen yogurt",
        "type": "Ice cream",
        "calories": { "value": 159.0 },
        "fat": { "value": 6.0 },
        "carbs": { "value": 24.0 },
        "protein": { "value": 4.0 },
        "sodium": { "value": 87.0 },
        "calcium": { "value": 14.0 },
        "iron": { "value": 1.0 }
      }, {
        "name": "Ice cream sandwich",
        "type": "Ice cream",
        "calories": { "value": 237.0 },
        "fat": { "value": 9.0 },
        "carbs": { "value": 37.0 },
        "protein": { "value": 4.3 },
        "sodium": { "value": 129.0 },
        "calcium": { "value": 8.0 },
        "iron": { "value": 1.0 }
      }, {
        "name": "Eclair",
        "type": "Pastry",
        "calories": { "value":  262.0 },
        "fat": { "value": 16.0 },
        "carbs": { "value": 24.0 },
        "protein": { "value":  6.0 },
        "sodium": { "value": 337.0 },
        "calcium": { "value":  6.0 },
        "iron": { "value": 7.0 }
      }, {
        "name": "Cupcake",
        "type": "Pastry",
        "calories": { "value":  305.0 },
        "fat": { "value": 3.7 },
        "carbs": { "value": 67.0 },
        "protein": { "value": 4.3 },
        "sodium": { "value": 413.0 },
        "calcium": { "value": 3.0 },
        "iron": { "value": 8.0 }
      }, {
        "name": "Jelly bean",
        "type": "Candy",
        "calories": { "value":  375.0 },
        "fat": { "value": 0.0 },
        "carbs": { "value": 94.0 },
        "protein": { "value": 0.0 },
        "sodium": { "value": 50.0 },
        "calcium": { "value": 0.0 },
        "iron": { "value": 0.0 }
      }, {
        "name": "Lollipop",
        "type": "Candy",
        "calories": { "value": 392.0 },
        "fat": { "value": 0.2 },
        "carbs": { "value": 98.0 },
        "protein": { "value": 0.0 },
        "sodium": { "value": 38.0 },
        "calcium": { "value": 0.0 },
        "iron": { "value": 2.0 }
      }, {
        "name": "Honeycomb",
        "type": "Other",
        "calories": { "value": 408.0 },
        "fat": { "value": 3.2 },
        "carbs": { "value": 87.0 },
        "protein": { "value": 6.5 },
        "sodium": { "value": 562.0 },
        "calcium": { "value": 0.0 },
        "iron": { "value": 45.0 }
      }, {
        "name": "Donut",
        "type": "Pastry",
        "calories": { "value": 452.0 },
        "fat": { "value": 25.0 },
        "carbs": { "value": 51.0 },
        "protein": { "value": 4.9 },
        "sodium": { "value": 326.0 },
        "calcium": { "value": 2.0 },
        "iron": { "value": 22.0 }
      }, {
        "name": "KitKat",
        "type": "Candy",
        "calories": { "value": 518.0 },
        "fat": { "value": 26.0 },
        "carbs": { "value": 65.0 },
        "protein": { "value": 7.0 },
        "sodium": { "value": 54.0 },
        "calcium": { "value": 12.0 },
        "iron": { "value": 6.0 }
      }
    ]
  };

  $scope.getTypes = function () {
    return ['Candy', 'Ice cream', 'Other', 'Pastry'];
  };

  $scope.onpagechange = function(page, limit) {
    var deferred = $q.defer();

    $timeout(function () {
      deferred.resolve();
    }, 2000);

    return deferred.promise;
  };

  $scope.onorderchange = function(order) {
    var deferred = $q.defer();

    $timeout(function () {
      deferred.resolve();
    }, 2000);

    return deferred.promise;
  };
}]);

Upvotes: 1

Views: 518

Answers (1)

Jon
Jon

Reputation: 3184

Solved. The solution is simple, and will be obvious to those who know what they're doing with regards to Angular.

I should have mentioned that I'm also new to Angular and I forgot the all-important html tag definitions. Here's the fix.

Before:

<html lang="">

After:

<html lang="en" ng-app="demoApp" class="ng-scope">

There are some styling conflicts between the data grid and the default Polymer element styling, but those are much easier to sort out.

Upvotes: 0

Related Questions