Portfolio site, Part 6: Adding a router

So far, I’ve been really happy using the Topeka app as a template for my portfolio site. However, it does not have a router. And, I want to be able to share direct links to some of my project pages, such as morganintrator.com/#upswing. Therefore, I must build a router for my single page application/portfolio site.

Check out the Topeka app. You’ll see that the url does not change as you navigate between pages. This means that you could never go straight to any particular quiz or category page when visiting the site. That may work for Topeka, but it doesn’t work for my site. I want to be able to share URLs that point to specific projects of mine. I don’t want everyone tohave tosee my bad ass turntable animation every time they come to morganintrator.com.

This means that I had to add my own router. In Angular, I’m used to using the Angular UI Router, which is quite sophisticated. Angular’s own router, ng-router, is bit underwhelming, which is why the Angular team completely rebuilt it for Angular 2.0.

But I need a polymer router. So, I started out by reading a variety of documentation.

  1. Thispage on Polymer’s website – a tutorial for building a single page application (SPA).
  2. The examples in that tutorial are on github here.
  3. The example that uses flatiron-director(a link to the base library)for routing is live here.
  4. The flatiron polymer component used in the example is here. You have to clone it or get the zip file (it doesn’t bower install).

After plugging in the flatiron-director component, I went back to morgans-app.html to listen for to the director-route event:

eventDelegates: { 'director-route': 'state' },

and this is essentially the router logic – it’s just one function:

state: function(route) { console.log("Hello state: "); console.log(route); //route.detail if (route.detail 'hits') { this.selected = 'hits'; window.location.hash = 'hits'; document.title = "Morgan's Greatest Hits"; } else if (route.detail 'me') { this.selected = 'me'; window.location.hash = 'me'; document.title = "About Morgan"; } else if (route.detail 'credits') { this.selected = 'credits'; window.location.hash = 'credits'; document.title = "Morgan Thanks..."; } else if (route.detail 'splash') { this.showSplash(); } else { if (this.loading) { this.async(function() { if (this.hitsHash[route.detail]) this.showHit(route.detail); else this.showSplash(); }, null, 1000); } else { if (this.hitsHash[route.detail]) this.showHit(route.detail); else this.showSplash(); } } this.history++; },

Of note is the loading property. this.loading is used to track whether the hits.json file has been loaded or not. If it is still loading, we wait a second before checking for the hit. If it’s not found (either it doesn’t exist, or the json still isn’t loaded), we go to the splash page.

That’s pretty much it. Although, I ran into several other challenges along the way:

Going directly to a “hit” page

I was having an animation issue loading the “hit page” if you went there directly. I had to put “if” statements on the hero animations, because there shouldn’t be any in that case. So, I created this.history to count the number of state transitions. That way, if we know the user just arrived to my page (this.history <= 1) and headed directly to a “hit” of mine, then we will use different animations for the page. I’m thinking the page should slide-up.

Visiting the same “hit” twice

I encountered an issue when trying to select the same hit twice. That is, after going back to the “hits” page and selecting the “hit” I had just seen. Using hitSelect withon-core-activate="{{hitSelect}}" in order to know when the user may have selected the same hit again won’t fire a selectedChanged event.I had to go looking at the old Topeka app to figure that one out – I had already deleted much of it. Here’s what did the trick:

Specifically, the hitSelect function did the trick. Check out what happens in the function on github.

Cache problems again (this time with JSON)

WhenI started editing content in hits.json, I spent an hour looking for bugs because it wouldn’t render (my assumption was it had to do with ‘extending’ the base-card.html). In fact, it was because chrome was caching hits.json even with the dev tools open (with dev tools open, it doesn’t cache html, at least). So, I had to keep pulling the latest hits.json file with this:

<core-ajax auto handleAs="json" url="{{url+nocache}}" response="{{hits}}"></core-ajax>
and <br></br>
publish: {<br></br>
nocache: '?'+ new Date().getTime()<br></br>

Injecting HTML via variables

Here’s an example of what’s in my hits.json file. Because some of the text includes links (anchor tags) or bold phrases (strong tags), I needed to have actual HTML render with polymer.

"about": [{ "label": "Team", "value": "Morgan" }, { ...

Injecting HTML into my cards required a new element, andI found atemplate here on the Polymer site. It had to be tailored some. Here’s what mine looks like: