Should I use Angular’s ngRouter in Framework7?

TL;DR

No, you shouldn’t use ngRouter with Framework7. Use ajax pages and set pushState:true instead!


I’m getting quite a lot of questions regarding the implementation of navigation in Framework7 apps with Angular.js. How do I use ajax pages with Angular? Does ngRouter work with F7? How can I get the back button in the browser to work in F7? And so on…

Best practice for ngRouter with F7

I don’t know if there is something like a "best practice" but so far for me it seems like it’s best to let F7 handle navigation as well as content integration. Mixing ngRouter with F7’s navigation system does not work well. There is no real point in using ngRouter anyway. Framework7 does an excellent job of fetching content via ajax pages and display the data at the right spot. You might want to enable the browser’s back button capability though by setting this option when initializing your app:

var myApp = new Framework7({
  pushState: true
});

Learn more about Ajax Pages with Angular

How to use ajax pages with Angular 1.x in Framework7

Since my last screencast about how to use F7 with Angular the most asked question that I got was about ajax pages, something like this:

"In your example you have all your pages in one html file but what if I separated each page into its own file using Framework7’s ajax pages mechanism? (read F7 docs about ajax pages).
If I use it, all the bindings from Angular do not work anymore. How do I fix this, oh mighty Timo?"

(Minor quote inaccuracies might be included)

Well, the problem here is that Framework7 will get each page via ajax (when a link that points to it is clicked) and then inject it into the DOM. Angular does not know anything about this and thus will not update any bindings. Luckily, there is an easy fix for this.

The solution to ajax pages with Angular

When you inject a new HTML snippet into the DOM via Ajax pages, you simply do:

$compile(snippet)($scope);
$scope.$apply();

(See demo source code for an example how to use this)

This will recompile the HTML snippet that got added and then apply the changes and BOOOOM, that’s it.

Note: You don’t want to do this to often as it affects performance quite a bit.

Demo

I also created a quick demo for you to check this out. In order to work you must serve it via http protocol from a web server like Apache or NGINX. Just double-clicking the index.html file and serving it via file:/// will not work because you cannot do ajax calls via file:///.

Get the demo on: Github

Experiment: An iPhone app built with Framework7, TypeScript, and AngularJS


Disclaimer: Since this post is getting quite some attention I have to state some things clear, so read this first!
This example is not best practice on how to use Framework7, it’s more of an experiment to see how it works with Angular and TypeScript. Framework7 has an own templating engine called Template7 so Angular is not mandatory. Also F7 designed to work with JavaScript, rather than TypeScript.
So, if you’re new to Framework7, do not assume that this example is the way you should create F7 apps! It was an experiment to see what happens if you combine these technologies. After all I can say that I wouldn’t use TypeScript with F7 again, just stick to plain old JavaScript. If you know how to use Angular, then you should be safe using it. If you don’t know Angular, then use Template7.

If you want to learn how to use Framework7 with AngularJS, go check out my video screencast tutorial!


In my last post I created a template for Framework7 based on TypeScript and Angular. Since Angular is still such a big hype and there doesn’t seem to be any examples of Framework7 with Angular, I decided to create a little demo application that demonstrates Angular’s data binding technique with TypeScript on top of Framework7. This demo will display lists of upcoming and current movies in theaters. Tapping on a movie will show additional information. The result looks like this:

Screenshot

Framework7 with Angular movie list demo

Demo

Check it out here: http://www.timo-ernst.net/misc/f7angulardemo/

Before you check the code, read this!

The demo code is based on this template for Framework 7. For some people this might look a little complicated since you will have to know how to use npm and grunt. So if you want a simpler version of the template without a compile process and just pure html, css and javascript, try this.

Code explanation

Let’s dive into the code. I’ll explain piece by piece what I did. At the bottom of this post you will find a link to Github where you can clone the repo and get the sources.

The view

To build this, I simply saved all movie data into a model “movies” and bound that with Angular expression to the view. In order to not repeat to many list item elements I used ng-repeat:

<ul>
  <li class="ft-movielist-item" ng-repeat="movie in movies">
    <a href="#detailsPage" ng-click="events.onListItemClicked(movie)" class="item-link">
      <div class="item-content">
        <div class="item-media">
          <img class="ft-movielist-item-img" src="{{movie.posters.thumbnail}}">
        </div>
        <div class="item-inner">
          <div class="item-title-row">
            <div class="item-title">{{movie.title}}</div>
          </div>
          <div class="item-subtitle">{{movie.stars}}</div>
          <div class="item-text">{{movie.synopsis}}</div>
        </div>
      </div>
    </a>
  </li>
</ul>

TypeScript model definition

Since TypeScript is well.. strictly typed we first need to define how our model looks like:

  export interface Movie{
    id:String;
    synopsis:String;
    title:String;
    posters:MoviePosters;
    ratings:MovieRatings;
    release_dates:MovieReleaseDates;
    stars:String;
    date:String;
  }

Data binding

I bound an empty array of this type as a model via angular scope:

var movies:Movie[] = [];
$scope.movies = movies;

Get the data and update the model

To fill the model array with data, I start an ajax call and then copy the data from the json response into my model array:

var ajaxconfig:ng.IRequestConfig = {
  method: 'JSONP',
  url: (type == 'upcoming' ? this.API_URL_UPCOMINGLIST : this.API_URL_THEATERSLIST)
};
 
// Do ajax call to rotten api
this.$http(ajaxconfig)
  .success((data: Movies.AjaxResultData, status: number, headers: (headerName: string) => string, config: ng.IRequestConfig): void => {
    // Update angular model
    angular.copy(data.movies, this.movies);
  })
  .error((data: Movies.AjaxResultData, status: number, headers: (headerName: string) => string, config: ng.IRequestConfig): void => {
    alert('Failed connecting to rotten tomatoes db. Status code ' + status);
  });

And boom! That’s it. Angular will automatically display the data in the view. When ever you modify the model, Angular will sync this to HTML.

No jQuery. No DOM manipulation. Enjoy :-)

Full source code

Download on GitHub

Lessons learned

Angular will greatly help to reduce your amount of javascript code. TypeScript is cool because of strict typing and support of classes but it will make your code much much more complicated. The stuff that you saw here in this post is just a tiny small part of the whole thing which involves modules, type declarations, path references, compiler nagging and a lot more (check the full source to see the whole disaster). So at the end it eats up all the code that Angular has saved. Next time I use Angular I will stick with JavaScript and ditch TypeScript which could be interesting though for Node apps. I’ll try that next time maybe. Framework7 is still the best HTML-based iOS framework that I have ever seen. It’s super fast and perfectly mimics the look and feel of native apps. Make sure to check it out: http://www.idangero.us/framework7/

Framework7 template with TypeScript and AngularJS

Important: Read this first!
This article covers a template for Framework7 apps built on TypeScript, SASS, Grunt and AngularJS. From my experience so far I discovered that TypeScript is really complicated and not much fun to use with F7 and Angular. Also, some people seem to struggle with the grunt compile process. So, I created a new, easier template without any fancy stuff, just plain HTML, CSS and JavaScript which I can recommend to get started before diving into the funky stuff: https://github.com/valnub/Framework7-Pure-Angular-Template (There is also a video screencast tutorial available)


Framework7

I am a big fanboy of Framework7, strict typing and MVC, so I tried to combine Framework7 with TypeScript and Angular with a flavor of SASS boiled on top of Grunt. The result is this ready-to-use template: Check on Github

How to build the Framework7 template

  1. No complicated bower or yeoman stuff. Just get from Github.
  2. Then, do npm install and then grunt compile to compile and copy everything from /src to /build. Default task for grunt is β€œwatch” which you can use for auto-compile and -reload in the browser when you do changes in /src.

Example app

If you need an example check out this demo app that I created on top of this template. It simply lists current and upcoming movies from rottentomatoes by getting the data via Ajax using Angular’s $http service as well as its integrated data binding technique to render the view.

Framework7 with Angular movie list demo

Let me know if you have any feature requests for the template.