AngularJS for Java Developers

Preview:

DESCRIPTION

An introduction to the AngularJS JavaScript MVC framework from Google. Tailored for Java developers. Presented at the Orange County Java Users Group on 10/09/2014

Citation preview

AngularJS for Java

Developers

Loc Nguyenlochnguyen@gmail.com

<ng-selfie/>

● Organizer of AngularJS-OC [angularjsoc.org, @angularjsoc]

● Multi-platform SW geek => Java, Ruby, JavaScript, C#, Node

● First an Ember fan (still am)

● ~1.5 years of AngularJS experience => mostly consulting

Agenda

● Thick client history

● Current state of JS

● MVC & Data binding

● Components

● Tooling

● Resources

How to train your dragon JavaScript

Ship It™

Ambitious Web Applications™

The Model

● Plain old Java(Script) objects – POJO!

● No need to extend a hierarchy

class Member {

String name = "";

boolean active = true;

List<String> emails = new List<String>();

}

var member = {

name: '',

active: true,

emails: []

};

The View

● Just plain HTML

● Built-in directives similar to JSTL

// index.jsp

<c:if test="${member.active}">

<c:out value="${member.name}"/>

<ul>

<c:forEach items="${member.emails}" var="email">

<li><c:out value="${email}"/></li>

</c:forEach>

</ul>

</c:if>

// index.html

<div ng-if="member.active">

{{member.name}}

<ul>

<li ng-repeat="email in member.emails">

{{email}}

</li>

</ul>

</div>

The Controller

● Plain old JavaScript functions

● Instantiated as needed

● Inject dependencies

● Figure out what the view needs, defer retrieval

● $scope is the context

o a view model

function meetupController($scope) {

$scope.person = {

name: 'Loc', active: true, emails: [...]

};

}

@Controller

class MeetupController {

public String index(Model model) {

Member person = new Member();

member.name = "Loc";

member.active = true;

member.emails = Arrays.asList(...);

model.setAttribute("scope", member);

}

}

package ocjug.controllers;

angular.module('ocjug.controllers', [])

.controller('MeetupController', meetupController);

Data Binding

● $digest loop – Angular event loop

● $watch list – what’s dirty?

● http://codepen.io/anon/pen/EcoGd

Dependency Injection

● Code to abstractions

● Testing is so easy

● SOLID

● Put controllers on a diet

Services

● Promote cleaner code

● Organization and reusability

● Shared business logic

● Data retrieval

● One instance in app

● 3 ways to make a service!

package ocjug.services;

@Service

class MeetupSearchService {

private final API_KEY = "abc123";

private final SEARCH_URI = "https://api.meetup.com/search";

@Autowired

SomeHttpClient httpClient;

public List<SearchResult> search(Map params) {

// start pseudo-ing

httpClient.queryParams(params).get(SEARCH_URI);

}

}

Example

angular.module('ocjug.services', [])

.factory('MeetupSearchSvc', function ($http) {

var API_KEY = 'abc123';

var SEARCH_URI = 'https://api.meetup.com/search';

var search = function (queryParams) {

return $http.get(SEARCH_URI, { params: queryParams

});

};

return {

search: search

}

});

Services

.service() - invoke with the new keyword

angular.module('ocjug.services', [])

.service('MeetupSearchService', function ($http) {

this.API = 'http://api.meetup.com/search';

this.search = function() {

// ...

}

});

Services (cont)

.factory() - always use a factory!

angular.module('ocjug.services', [])

.factory('MeetupSearchService', function ($http) {

var API = 'http://api.meetup.com/search';

return {

search: function (params) {

// …

}

};

});

Services (cont)

.provider() - configure before app starts

angular.module('ocjug.services', [])

.provider('MeetupSearchProvider', function () {

var API = 'http://api.meetup.com/search';

this.REMEMBER_SEARCHES = false;

this.$get = function ($http) {

return {

search: function (params) {

// …

if (this.REMEMBER_SEARCHES) ...

}

};

};

});

Services (cont)

angular.module('ocjug', ['ocjug.services'])

.config(function(MeetupSearchProviderProvider) {

MeetupSearchProviderProvider.REMEMBER_SEARCHES = true;

});

angular.module('ocjug.controllers', [])

.controller('MemberSearchCtrl', function ($scope, $http) {

$http.get('http://api.meetup.com/search?name=' +

$scope.name);

})

.controller('MeetupSearchCtrl', function ($scope, $http) {

$http.get('http://api.meetup.com/search?meetup='

+ $scope.meetup);

});

Extracting into a Service

var ocjug = angular.module('ocjug', ['ocjug.services']);

function memberSearchCtrl ($scope, MeetupSearchSvc) {

MeetupSearchSvc.search({ name: $scope.name });

}

ocjug.controller(MemberSearchCtrl, memberSearchCtrl);

function meetupSearchCtrl ($scope, MeetupSearchSvc) {

MeetupSearchSvc.search({ meetup: $scope.meetup });

}

ocjug.controller(MeetupSearchCtrl, meetupSearchCtrl);

Filters

● Take an input to filter

● Easily format data in templates

● Uses the | character in {{ }} expression

{{1.456 | number:2}} => 1.46

{{'ocjug'| uppercase | limitTo:3}} => OCJ

{{99.99 | currency:'USD$' }} => USD$99.99

<div ng-repeat="m in movies | orderBy:'revenue'">

angular.module('ocjug.filters', [])

.filter('asCentimeters', function () {

return function (inches) {

return inches * 2.54;

};

});

{{2 | asCentimeters}} => 5.08

Directives

● The killer feature of AngularJS

● ...and the most complex API

● Apply liberally

Directives

● Built-in directives

○ ng-show, ng-click, ng-repeat

● Custom directives

○ reusable widgets

○ declarative programming

○ wrap non Angular libraries

<div ng-repeat="picture in pictures">

<pic picture="picture"

commentable="{{picture.approved}}"></pic>

</div>

// picture.tpl.html

<div>

<img ng-src="picture.url"/>

<div>{{picture.caption}}</div>

<a ng-click="fbLike(picture)">Like</a>

<ul>

<li ng-repeat="comment in picture.comments |

limitTo:3">

{{comment}}

</li>

</ul>

<comment-form picture="picture"> … </comment-form>

</div>

angular.module(ocjug.directives, ['ocjug.services'])

.directive('pic', function(FbService) {

return {

templateUrl: 'picture.tpl.html',

scope: {

picture: '=',

commentable: '@'

},

link: function ($scope, el, attrs) {

$scope.fbLike = function(picture) {

FbService.like(picture.id);

}

}

}

});

angular.module(ocjug.directives, ['ocjug.services])

.directive('commentForm', function(CommentService) {

return {

templateUrl: 'comment.tpl.html',

scope: {

picture: '='

},

link: function ($scope, el, attrs) {

$scope.submit = function(comment) {

CommentService.create(comment);

}

}

}

});

Test and Tools

● Unit tests - Karma

● E2E - Protractor

● Node based build toolso Grunt

o Gulp

What’s missing?

● SPA vs Islands of Richness

● Async and promises

● AJAX

● Performance

● Routing

● Testing

● Mobile

● Integration

Resources

UI-Router: github.com/angular-ui/ui-router

Angular-UI: github.com/angular-ui

Ionic: ionicframework.com

Year of Moo: yearofmoo.com

Style Guide: github.com/johnpapa/angularjs-

styleguide

docs.angularjs.org/tutorial

● Free!

● Beginner

codeschool.com

● Free!

● Gamified learning

● Beginner

egghead.io● AngularJS,

● JavaScript,

● D3.js

● EcmaScript 6

● NodeJS

● ReactJS

● $10m or $100/y

https://egghead.io/pricing?dc=ng_socal

Beginner – Advanced

pluralsight.com

● $29 month

● The most Angular courses

● Deep coverage of JS

● ...and .NET

● Beginner – Advanced

$23$40

angularjsoc.org

meetup.com/AngularJS-OC

Recommended