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/

28 thoughts on “Experiment: An iPhone app built with Framework7, TypeScript, and AngularJS

  1. Well, nice article, BUT not much learned due the fact that you have the main functionality as an import.
    Ideally, you should include all the stuff in the download. The goal being that when the code is downloaded, it should work with zero imports. The import creates a big dependency and renders your efforts to be not very useful for folks without internet connection.
    …just a thought.
    cheers,
    beno

  2. What I meant is that the downloaded code does not work probably due to some missing dependencies that have to be imported. The user that downloads your code expects to have all the needed files for it to run included in the download, but I don’t think that is the case here. To test your application, I followed these steps:
    Step 1: Download. Step 2: Unzip: Step 3: Move all files in unzipped folder to a NEW folder I created. Step 4: Call http://localhost/Newfolder/index.dev.
    Expected behavior is for application to load.
    Actual behavior was that application failed.
    So Questions: How do you run your app on a local box? What are the dependencies for your app to work?
    Being that it is simply javascript, it should actually run on any webservser. So I am assuming there are actually some dependencies that needs to be imported for it to work, if not, what are the steps for it to work?
    cheers,
    beno

  3. @beno

    Oh, ok I see what your problem is. Actually there is nothing special about the code, it follows the regular workflow using npm and grunt. If you’re not familiar with that, I recommend reading up on that. They’re both de facto standards:

    https://www.npmjs.com
    http://gruntjs.com

    Besides that, you shouldn’t download the zip file. Usually you want to use git to check out (clone) the repository and work with that.

    You’re right, there are dependencies and they’re not checked in but that’s on purpose because it’s not good practice to check in modules and libraries. Instead, I recommend using npm to download the dependencies. Follow these steps:

    1. Clone the git repo
    2. Make sure you have npm and grunt installed
    3. Get the dependencies via npm by calling “npm install” from the project folder (not src folder!). Npm will download and install all dependencies automatically.
    4. Now call “grunt compile” from the project folder and Grunt will create a fresh build for you with only 1 clean index.html file.

    What’s important: For development, edit the .dev html files but do not deploy these! It doesn’t make any sense and of course it won’t work. Instead, deploy the result of the grunt build (look inside the “build” folder) to your web server.

    Again: Do not copy the .dev files to your web server. It won’t work. Let grunt create a build and deploy that.

  4. Eric says:

    First of all, thank you for the amazing work !
    Could you give insight on how to use f7 + angular without typescript, as you suggest it will be your way to go ?
    I am trying to to so but fail to initialize the controller, especially out of index.html (which works fine without f7)

  5. Eric says:

    Sorry to ask again, but I only manage to get angular work ok on single page application with all the views in a single html file as your example shows, but not if I link to another html file containing the view (which is cleaner for a larger app). The controller isn’t loaded and angular tags do no seems to be interpreted. Could you help me on this ?

  6. Knollan says:

    Hi! Thanks for this tutorial. But I can’t seem to follow that much. Where do I define the type script model definition? Basically I have 2 js files included on my index.html (the js file for the angular and the myApp.js), do I still need a script for my specific page inside myApp.js? It might help if I can see the source exactly.

    I’m sorry but I’m very new to this and angular, but I need to use this on one of my client’s project. Thanks in advance.

  7. @Knollan Why don’t you check out the source code example? :-) https://github.com/valnub/Framework7-with-AngularJS-demo-app/tree/master/src/ts/ft

    Remember that this example is based on Typescript! So if you used plain js you won’t need model definitions!

    The Typescript model is here: https://github.com/valnub/Framework7-with-AngularJS-demo-app/blob/master/src/ts/ft/model/movies/Movies.ts

    If this is to complicated for you, there is also an easier version of the template available without Typescript: https://github.com/valnub/Framework7-Pure-Angular-Template

  8. @zenhao Well, I don’t know since I have never used Meteor before, but I got an email from someone several weeks ago who asked me if I wanted to collborate in a project to integrate F7 into Meteor, so I guess it might be possible but I’m not sure of that. I can recommend F7 forums, maybe someone over there knows: http://www.idangero.us/framework7/forum/

  9. Artem says:

    Hi! Your app looks pretty good since I’ve been investigating the possibility of integrating Framework7 with one of the MV* frameworks (knockoutjs, angularjs, backbonejs, reactjs, etc.). So, one of the obstacles when dealing with knockout, for instance, was that f7 uses css pseudo classes for checkboxes, radio buttons, switches so it’s impossible to bind a checkbox to a field in the viewmodel (since the markup DOESN’T differ when checking/unchecking an element), at least out of the box.
    So, keeping in mind that your demp app is not that rich in variety of UI controls provided by Framework7 my question is whether you’ve tried anything more complicated (checkboxes for example, http://www.idangero.us/framework7/docs/checkboxes-radios.html)?
    Have you had your hands on any other similar framework except angularjs?

  10. Yujing says:

    Hi.Thanks for you share.I also want to using Framework7 and Angularjs to build a website app.I had downloaded this demo app and grunt compile this project then run with nginx.But here comes question.I have got “Uncaught SyntaxError: Unexpected token <" error when I run 'http://localhost:3232&#039;.Have anyone appear problem like this?In addition ,I work with Linux.

  11. Yujing says:

    Uncaught SyntaxError: Unexpected token <
    Movies.js:1
    Uncaught SyntaxError: Unexpected token <
    PageController.js:1
    Uncaught SyntaxError: Unexpected token <
    IndexPageController.js:1
    Uncaught SyntaxError: Unexpected token <
    DetailsPageController.js:1
    Uncaught SyntaxError: Unexpected token <
    init.js:1
    Uncaught SyntaxError: Unexpected token <
    MINERR_ASSET:8
    Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.3.15/$injector/modulerr?p0=ft&p1=Error%3A%20%…(http%3A%2F%2Flocalhost%3A3232%2Flib%2Fangular%2Fangular.min.js%3A17%3A381)(anonymous function) @ MINERR_ASSET:8(anonymous function) @ angular.js:3953r @ angular.js:215g @ angular.js:3850ab @ angular.js:4170d @ angular.js:1190uc @ angular.js:1246Jd @ angular.js:1147(anonymous function) @ angular.js:19141a @ angular.js:14831c @ angular.js:3475

    This is amazing to see these errors. Is my wrong configuration?

  12. @Yujing Hm, this is very weird. Can you zip your sourcecode, upload it somewhere (e.g. Dropbox) and send me link to download?

  13. Yujing says:

    Hi Timo,I didn’t change anything and anywhere,just download the code in github,follow the step you gived.So,I am very confused
    .At your request,I had ziped all my sourdecode ,including build/ file to Baidu Cloud >>http://pan.baidu.com/s/1gdyKw3T >To extract the password: a93g.

  14. Raf says:

    Hi there do you know if its possible to use Angular and ajax injected pages from Framework 7? At the moment the child page does not load Angular??? Do I need to ad some kind of DOM watch?

    index.html

    About

    about.html

    Thanks

  15. @Raf I do not use injected pages since I am not a big fan of those. I rather put everything into 1 html file or if I have a lot of markup, I use multiple html pages and compile them together statically using Grunt or Gulp.

    However, you might be able to accomplish what you want using Angular’s $compile module, but I’ve never tried that before: http://excellencenodejsblog.com/angularjs-compile-parse-interpolate/

    Edit: I’ve posted a solution on my blog which works pretty well for me: http://www.timo-ernst.net/blog/2016/02/24/how-to-use-ajax-pages-with-angular-1-x-in-framework7/

  16. Raf says:

    Hi Timo thanks for your answer I’m using the Telerik App builder so I have access to Angular, Typescript but the windows client does not have Grunt or Gulp. I’m also trying to use:

    <!– – [Page 1] – –>

    <!– – [Page 2] – –>

    rather than your includes @@… however I’ve noticed I’m loosing click even on the list…strange.

    Thanks

  17. @Raf Are you trying to use the demo without Grunt? That won’t work. You must install Grunt first and then follow the instructions under “How to build” here: https://github.com/valnub/Framework7-with-AngularJS-demo-app

    If you don’t use Grunt there is nothing that could resolve the @@include statements. Thus, some part of your HTML is probably lacking when you run the app (which would explain why your click events don’t work).

    Ps. As a programmer, get a Mac.

Leave a Reply