1

I am very new to Polymer but am testing things out by using the Polymer Template:

https://www.polymer-project.org/1.0/start/toolbox/set-up

Everything is working correctly except when I type in a direct url, for example site.com/page

app-route: https://github.com/PolymerElements/app-route will load things correctly if I click a href link with /page however will not load correctly if I type in the url directly (I get a 404 error).

What am I missing? I haven't change any code from the demo app (demo app doesn't work for me when I type in the url directly).

tony19
  • 125,647
  • 18
  • 229
  • 307
  • Works fine for me in OSX El Capitan, Chrome 51. What's your test environment? And what exactly did you type? – tony19 Jun 01 '16 at 20:19
  • I'm using MAMP on OSX El Capitan 10.11.5 on Chrome Version 50.0.2661.102 (64-bit) It's very odd because I setup a site on MAMP at polymer/ and it works when I click a href but when I type in polymer/somelink it's a 404. – ChristopherRose Jun 01 '16 at 20:30
  • 2
    You'll probably have to add logic to your server to serve index.html for other sub routes in your app. I'm guessing your server is like "hey dog, there's no HTML file here named /some/subpath!" – Calvin Belden Jun 06 '16 at 14:35
  • what are u doing with "hashbang" ? do you need to include it in browser's location? see http://stackoverflow.com/questions/30925003/polymer-routing-with-page-js-do-not-add-hashbang-to-urls-when-links-are-opened-i – Robert Rowntree Jun 25 '16 at 15:22
  • Did you solve the problem?I'm having the same issue ,and there is nothing on internet about it. –  Dec 14 '16 at 15:01
  • Unfortunately no. I have decided to wait until the Polymer ecosystem/web components have matured. – ChristopherRose Dec 14 '16 at 15:02
  • @ChristopherRose Please make sure to review the answers below. If they help you make sure to upvote and accept them! If they don't, please leave comments explaining why they aren't helpful. – AP. Mar 09 '17 at 23:02

4 Answers4

2

You need to add a .htaccess file where index.html is. Here is a full working code for routing and iron-pages in it.

.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>....</title>
    <meta name="description" content="....">

    <link rel="manifest" href="/manifest.json">
    <link rel="import" href="/src/main-app.html" async>

    <style>

      .....
    </style>

  </head>
  <body>
    <main-app></main-app>
    <script>
      window.performance && performance.mark && performance.mark('index.html');

      Polymer = {lazyRegister: true, dom: 'shadow'};

      (function() {
        if ('registerElement' in document
            && 'import' in document.createElement('link')
            && 'content' in document.createElement('template')) {
          // platform is good!
        } else {
          // polyfill the platform!
          var e = document.createElement('script');
          e.src = '/bower_components/webcomponentsjs/webcomponents.min.js';
          document.body.appendChild(e);
        }
      })();
    </script>
  </body>
</html>

main-app.html

 <!-- START OF IMPORTS -->
    <link rel="import" href="../bower_components/polymer/polymer.html">
    <!-- Iron Ajax -->
    <link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
    <!-- Route -->
    <link rel="import" href="../bower_components/app-route/app-location.html">
    <link rel="import" href="../bower_components/app-route/app-route.html">
    <!-- Iron Pages-->
    <link rel="import" href="../bower_components/iron-pages/iron-pages.html">







    <!-- Fragments -->
    <link rel="import" href="you-page-to-go-to.html">



    <dom-module id="main-app">
      <template>
      <style>
     ....
      </style>

      <!-- App Routing -->
      <app-location route="{{route}}"></app-location>
      <app-route
      route="{{route}}"
      pattern="/:page"
      data="{{routeData}}"
      tail="{{subroute}}">
      </app-route>


  <iron-pages role="main" selected="[[page]]" attr-for-selected="name" selected-attribute="visible">
                <!-- General -->
                <you-page-to-go-to name="you-page-to-go-to"></you-page-to-go-to>
              </iron-pages>

    </template>

    <script>
    Polymer({
      is: 'main-app'
      properties: {
        page: {
          type: String,
          reflectToAttribute: true,
          observer: '_pageChanged'
        },
        title:{
          type:String,
          value:"null"
        }
      },
      /* For route */
      observers: [
        '_routePageChanged(routeData.page)'
      ],
      _routePageChanged: function(page) {
        this.page = page || 'home';
        this.drawerOpened = false;
      },
      _pageChanged: function(page, oldPage) {
        if (page != null) {

          this.title = page;

          this.importHref(
            this.resolveUrl('main-' + page + '.html'),
            function() {
              this._pageLoaded(Boolean(oldPage));
            }, null, true);
          }
        },
        _pageLoaded: function(shouldResetLayout) {
          if (shouldResetLayout) {
            this.async(function() {
            }, 1);
          }
        },

      });
      </script>
    </dom-module>
1

I had that problem too.after hours of searching I didn't find any solution for it. I had to find my own solution and I succeed finally. You have 2 options:

  1. use use-hash-as-path attribute on app-location (it's not SEO friendly)
  2. tune your web server configuration and redirect all of 404 requests to home

I'm using the option 2 and my web server is the IIS.

behzad besharati
  • 5,873
  • 3
  • 18
  • 22
0

This is an issue with your server configuration. When you first load up the up, your server knows that it needs to serve the index.html file, because all webservers default to this file.

Then when you click on a link, it's not asking the server for that url... it's running javascript to change the dom. The javascript is the entity doing the rewriting, and requests a raw html file, which your server knows how to find.

Now when you try to go to a url directly, your server looks for that "file" and can't find it, so you get a 404.

To fix this, you need to create proper rewrite rules in your server config. Most of the time, you do something like

try_file $uri index.html;

in nginx. This tells your server, hey, if you didn't find something at that address, don't 404... let the go to index.html and let the javascript handle it.

Booker
  • 756
  • 1
  • 5
  • 16
0

You need to have your back-end route all requests (no matter the URL/Path being requested) to the same page (index.html maybe?)

Polymer's app router will deal with the rest...

Explanation: When you type the URL into the browser, this happens:

  • Browser tries to match route with an HTML file
  • If it can't find one you get a 404

What you really want is app-router to take care of this, but how can that happen when your HTML is not loaded!

Therefore, depending on your server stack you want to have all /app/* type of routes to load the index.html file. Doing this will send pages like /app/home, /app/settings,/app/foo/bar all to index.html. Then app-router reads the window.location variable to match the URL to one of its route patterns, and then run the appropriate callbacks.

Does this make sense?


Front-end difference: (technical explanation on the difference)

When you are normally interacting with your app and the URL changes, no web requests are made to the server. In fact what the browser does here is that it modifies the browser's history stack using browser push-states. This allows the front-end to modify the url and the browser history to keep state without reloading the entire page every-time.

AP.
  • 8,082
  • 2
  • 24
  • 33