How to instantiate route in a Polymer app located on an internal page of a site using page.js

2.9k views Asked by At

I'm attempting to run a Polymer app on an internal page of a site and having an issue setting the initial route. The app is located at 127.0.0.1:8080/hardware on local dev.

My custom Element looks like this:

<link rel="import" href="../../polymer/polymer.html" />
<link rel="import" href="../../iron-flex-layout/iron-flex-layout.html" />
<link rel="import" href="../../iron-pages/iron-pages.html" />
<link rel="import" href="../../iron-selector/iron-selector.html" />

<dom-module id="category-select">
  <style>
    :host {} iron-selector {
      @apply(--layout-horizontal);

@apply(--layout-wrap);

@apply(--layout-justified);

    }
    .fig-wrap {
      @apply(--layout-flex);

margin: 0 .8rem;
      min-width: 150px;
    }
    .fig-wrap figure img {
      margin: 0 auto;
      display: block;
    }
    figcaption {
      padding-top: 5px;
    }
    .fig-wrap figure figcaption h3 {
      font-size: 1rem;
      text-align: center;
    }
  </style>
  <template>

    <!--Allows selection by dom elements produced in template repeater-->

    <h1>Hey We are looking at the  <span>{{category}}</span>category</h1>
    <a data-route="home" href="/hardware">home</a>
    <iron-pages attr-for-selected="data-route" selected="{{route}}">

      <section data-route="home">
        <h1>Home route</h1>
        <a data-route="catz" href="/catz">CATZ</a>
        <iron-selector attr-for-selected="name" selected="{{category}}">
          <!-- Acts as a for each loop to repeat-->
          <template is="dom-repeat" items="{{categories}}">
            <div name$="{{item.name}}" class="fig-wrap">
              <!--<a href="{{item.link}}">-->
              <figure>
                <img src="{{item.img}}" alt="" />
                <figcaption>
                  <h3>{{item.name}}</h3>
                </figcaption>
              </figure>
              <!--</a>-->
            </div>
          </template>
        </iron-selector>
      </section>

      <section data-route="catz">
        <h1>Category route</h1>
      </section>
    </iron-pages>
  </template>
</dom-module>
<script>
  Polymer({
    is: 'category-select',
    ready: function() {
      this.categories = [{
          name: 'Anchors',
          img: 'https://example.com/img/hardware/anchor.jpg',
          link: 'https://www.example.org/',
          products: [{
            name: 'Anchor',
            image: 'path/to/image.jpg',
            steel: '316 Stainless Steel',
            details: ['precision cut', 'polished from grade 316 stainless steel', 'suitable for both sailboats and powerboats', 'these anchors range in size from 25 lbs to 150 lbs'],
            options: [{
              size: '25 pounds',
              price: '3041.75',
              code: '32442'
            }, {
              size: '35 pounds',
              price: '4203.25',
              code: '4234'
            }, {
              size: '45 pounds',
              price: '5146.25',
              code: '34231'
            }, {
              size: '60 pounds',
              price: '6842.50',
              code: '1224'
            }, {
              size: '80 pounds',
              price: '8912.50',
              code: '1234'
            }, {
              size: '100 pounds',
              price: '11183.75',
              code: '1234'
            }, {
              size: '150 pounds',
              price: '14547.50',
              code: '1234'
            }]
          }, {
            name: 'Cast Iron Grapnel Folding Anchor',
            image: 'string',
            steel: 'Cast Iron Galvanized',
            details: ['products details', 'put them in a list', 'a pretty ul'],
            options: [{
              size: 'string',
              price: 'string',
              code: 'string'
            }]

          }, {
            name: '360° Anchor Swivel',
            image: 'string',
            steel: '17-4 PH Stainless Steel',
            details: ['products details', 'put them in a list', 'a pretty ul'],
            options: [{
              size: 'string',
              price: 'string',
              code: 'string'
            }]

          }, {
            name: 'Universal Anchor Swivel',
            image: 'string',
            steel: '17-4 PH Stainless Steel',
            details: ['products details', 'put them in a list', 'a pretty ul'],
            options: [{
              size: 'string',
              price: 'string',
              code: 'string'
            }]

          }, {
            name: 'Bow Chain Stopper',
            image: 'string',
            steel: '316 Stainless Steel',
            details: ['products details', 'put them in a list', 'a pretty ul'],
            options: [{
              size: 'string',
              price: 'string',
              code: 'string'
            }]

          }, {
            name: 'Anchor Chain & Spliced Rope Anchor Line',
            image: 'string',
            steel: '316L Stainless Steel & 3 Strand Twist',
            details: ['products details', 'put them in a list', 'a pretty ul'],
            options: [{
              size: 'string',
              price: 'string',
              code: 'string'
            }]
          }]
        }, {
          name: 'Chain',
          img: 'https://example.com/img/hardware/chain.jpg',
          link: 'https://www.example.com/'
        }

      ];
    },
    properties: {
      category: {
        computed: '_computeCategory(categories, name)'
      }
    },
    _computeCategory: function(categories, name) {
      return categories[name];
    }
  });
</script>

The custom element is wrapped in a <template is="dom-bind" id=app> on the page.

My routing.html is called from elements.html which looks like this:

<!--Elements from polymer-->
<link rel="import" href="../iron-selector/iron-selector.html"/>
<link rel="import" href="../iron-image/iron-image.html"/>
<link rel="import" href="../paper-button/paper-button.html"/>
<link rel="import" href="../paper-material/paper-material.html"/>
<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"/>
<!--Custom Elements-->
    <!-- app-theme goes here-->
<link rel="import" href="../elements/category-select/category-select.html"/>

<!--Configure routes-->
<link rel="import" href="routing.html"/>

And routing.html looks like this:

<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<script src="../page/page.js"></script>
<script>
    window.addEventListener('WebComponentsReady', function() {
        var app = document.querySelector('#app');

        // We use Page.js for routing. This is a Micro
        // client-side router inspired by the Express router
        // More info: https://visionmedia.github.io/page.js/
        page('/hardware', function () {
            app.route = 'home';
        });
        page('/catz', function () {
            app.route = 'catz';
        });
//
//        page('/users', function () {
//            app.route = 'users';
//        });
//
//        page('/users/:name', function (data) {
//            app.route = 'user-info';
//            app.params = data.params;
//        });
//        page('/categories', function () {
//            app.route = 'categories';
//        });
//
//        page('/categories/:name', function (data) {
//            app.route = 'category-info';
//            app.params = data.params;
//        });
//
//
//        page('/contact', function () {
//            app.route = 'contact';
//        });
//        page('/anchors', function () {
//            app.route = 'anchors';
//        });

        // add #! before urls
        page({
            hashbang: true
        });

    });
</script>

I call this script at the bottom of the page:

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  var app = document.querySelector('#app');
  app.route = 'home';


})(document);

So as a note, before adding the <iron-pages> element my iron selector and dom-repeat template functioned.

My issue now is that when <iron-pages attr-for-selected="data-route" selected="{{route}}"> has its selected set to {{route}} the iron-pages will not display any of the sections but displays a url of hardware/#!/hardware.

When I set iron-pages selected attribute manually to selected="home" the home view displays and iron-selector and dom-repeat both function. Yet when I click on the link to the route catz the view remains the same while the url changes.

console.log(app.route) in the dev tools returns home at all points. I've done my best to emulate the Polymer 1.0 Starter Kit's routing methods but cannot get it to work.

So, how do I go about setting the route to home initially, but then allowing it to change on user interaction?

1

There are 1 answers

5
robdodson On BEST ANSWER

For anyone else who is stuck on this. This Github issue hints at replacing

page({
  hashbang: true
});

with

page.base('#!')

This seems to help the initial load problem but then you run into issues where clicking links like /hardware don' use hashbangs anymore :\