iOS Developer Learning AngularJS
How I make a simple web app using AngularJS and Parse as backend in less than a day
For no particular reason I wanted to learn web app development. There are many frameworks out there to help developing web app easier. But I chose to go to the one made by the king of the Internet, Google. I'm gonna share how I made this stupid clickbait title generator in few hours using AngularJS.
Few notes before I get started, I'm using Mac with Yosemite. For text editor I'm using Atom. The source code of the clickbait generator is in Github. Actually, the web app itself is hosted in Github because there is no need for a web server. The recent titles are stored in Parse.
Now let’s talk about the app. The app will provide user with two text fields, the who textfield and doing what text field. Once both fields are filled, the app will automatically show the generated title. The app also has a Generate button which will randomly chose the exaggerated expressions to create the clickbait title. User can also submit the title and it will be shown in the recently created titles section. Pretty simple.
When developing iOS app, I can just open Xcode, create New Project, and boom, Xcode will provide all the files needed to quickly get started. For web app development, there is Yeoman. If you check the website, you can easily install it using npm.
npm install -g yo
After Yeoman is installed, let's install the Angular generator.
npm install -g grunt-cli bower yo generator-karma generator-angular
Now make a directory for the project. Then inside the directory create new angular app using yeoman:
yo angular clickbait
Boom. Yeoman will create all the necessary files. Once it's done, you can preview the app by running grunt, the task runner.
grunt serve
serve argument will open your app in the browser and reload it whenever it detects changes.
Yeoman generated some controllers, routes, and views for you. But I didn't know that and ended up generating a new route called home using
yo angular:route home
You can use the generated route, or you can just create a new one. When you run the command above, it will create a controller, a view, and configure a route in app/scripts/app.js.

The route code in app.js is pretty easy to understand. Opening the web app will redirect to '/' which will load views/home.html and HomeCtrl. If you look at app/index.html, you will see
<div class=”container”>
<div ng-view=””></div>
</div>
Angular will render the home.html into the div with ng-view directive.
Let's take a look at views/home.html step by step.
<p>Who? <input ng-model=”who” placeholder=”A man, A woman, etc”></p>
<p>Doing what? <input ng-model=”doing” placeholder=”sitting on the beach”></p>
<p><span ng-bind=”result()” class=”result”></span></p>
The first line is to show Who? with textfield. We use ng-model="who" directive to bind the text field value to "who" variable which we will access in Home controller. The same goes with Doing textfield. Then we show the generated title in the span tag. We bind the span tag with result() function which will be available in Home Controller using ng-bind="result()" directive.
In controllers/home.js, the file for Home controller, I added
$scope.result = function() {
if (!$scope.who || !$scope.doing) {
$scope.buttonDisplay = false;
return ‘’;
}
$scope.buttonDisplay = true;
return $scope.who+’ ‘+$scope.doing+’. ‘+$scope.bait;
};This is the result() function that will return the generated title. If who and oing are empty we return empty string. When user types something in who and doing textfield, Angular will automatically update the value of who and doing variable, which in results will automatically update the returned value of results() function. Since we bind the content of span tag with the result() function, the generated title will automatically appear. Pretty cool.
The same concept applies to the visibility of the buttons. To dynamically change the visibility of elements, Angular provides ng-show directive. So by simply assigning a variable to this directive, we can show or hide an element by assigning true or false in the controller. In this app, I used buttonDisplay variable to control the visibility.
Next we need to let the app to talk with Parse service. There is no official Angular support from Parse, but there is an open source patch for Parse SDK to work natively with AngularJS. But since all I wanted to do is simply fetch the latest titles and post a title, I figured I could just connect to Parse using the REST API.
At the beginning I used Angular's $http service to send POST and GET request to Parse inside Home controller.
// to fetch
var req = {
method: 'GET',
url: 'https://api.parse.com/1/classes/Pool?order=-createdAt&limit=100',
headers: {
'X-Parse-Application-Id': 'parse-app-id',
'X-Parse-REST-API-Key': 'parse-api-key',
'Content-Type': 'application/json'
},
};
$http(req).success(function (data) {
var results = data.results;
$scope.titles = results;
if ($scope.titles.length > 0) {
$scope.poolDisplay = true;
}
}).error(function () {
});
// to submit title
var req = {
method: 'POST',
url: 'https://api.parse.com/1/classes/Pool',
headers: {
'X-Parse-Application-Id': 'parse-app-id',
'X-Parse-REST-API-Key': 'parse-api-key',
'Content-Type': 'application/json'
},
data: {
'title': title
}
};
$http(req).success(function () {
$scope.submitDisabled = false;
$scope.reloadPool();
}).error(function () {
$scope.submitDisabled = false;
});
But there is a better way to avoid repetition. We can create a custom Angular service to serve as a client for Parse.
yo angular:factory Title
This will create services/title.js file in which we can implement our RESTful client. I used ngResource service to interact with Parse.
// services/title.js
angular.module(‘RestService’, [‘ngResource’])
.factory(‘Title’, [‘$resource’, function ($resource) {
var clickbaitAppHeaders = {
‘X-Parse-Application-Id’: ‘parse-app-id’,
‘X-Parse-REST-API-Key’: ‘parse-api-key’,
‘Content-Type’: ‘application/json’
};
return $resource(‘https://api.parse.com/1/classes/Pool', {}, {
get: {
method: ‘GET’,
params: {
‘order’: ‘-createdAt’,
‘limit’: 100
},
headers: clickbaitAppHeaders
},
post: {
method: ‘POST’,
params: {
title: ‘’
},
headers: clickbaitAppHeaders
}
});
}]);
Now that we have a service called Title, we can use it in our controller.
// scripts/controllers/home.js
angular.module(‘clickbaitApp’)
.controller(‘HomeCtrl’, [‘$scope’, ‘$http’, ‘Title’, function ($scope, $http, Title) {
...
Title.get({}, function (res) {
$scope.titles = res.results;
if ($scope.titles.length > 0) {
$scope.poolDisplay = true;
}
});We get the titles from Parse and assign it to variable 'titles'. All we need to display them is to bind some elements in the view to this variable. To display multiple items, Angular has ng-repeat directive.
// views/home.html
<div ng-repeat=”title in titles”>
<span am-time-ago=”title.createdAt” class=”createdAt”></span> {{title.title}} <a href=”https://twitter.com/intent/tweet?text={{textToTweetForTitle(title.title)}}" target=”_blank”>Tweet this</a>
</div>
It basically means for each element in variable titles, repeat the elements inside the div tag. titles variable is an array that contains objects fetched from Parse. So to display the title from each of the objects, we need to get the title property of that object
{{title.title}}And that's it. You can explore the code in Github or browse through the AngularJS Tutorial. There are several ways to deploy a Yeoman web app to production. I just used git subtree to deploy to github pages.
grunt build
git subtree push --prefix dist origin gh-pages
It was pretty fun. The best part was the fact that the app can be online and available for people to try immediately. There's no need to wait for a week to release the app.
Well then, back to making iOS apps. Have you checked my apps?