AngularJS Best Practices

80
AngularJs Best Practices

description

Here is a compilation of best practices at Betclic on Angular JS

Transcript of AngularJS Best Practices

Page 1: AngularJS Best Practices

AngularJs Best Practices

Page 2: AngularJS Best Practices

• File Organization• Namespacing and File naming• Understanding Modules• Organizing modules• Minification• Definitions and roles• Controllers• Services • Directives• Scope• Communicating between components• Avoiding FOUC• Thinking Declaratively• Directives as a DSL• Breaking Down A Page into Components• $resource• Restangular• Betclic best practices• Conclusion

Agenda

Note: all screenshots are copyright from their respective owners.

Page 3: AngularJS Best Practices

• Basic

Only for a small POC app

3

File Organization

Page 4: AngularJS Best Practices

• By feature

4

File Organization

Page 5: AngularJS Best Practices

• By feature then type

If more than 15 files , split by type

Don’t forget that the file organization doesn’t reflect how code is delivered

5

File Organization

Page 6: AngularJS Best Practices

• Miror app file organization for unit test

• Keep same file name + ‘Test’

6

File Organization

Page 7: AngularJS Best Practices

• Why naming ?

– Object type reading

– Avoid collisions (silent with Ajs!)

7

Namespacing and File naming

Page 8: AngularJS Best Practices

• NameSpacing solution (2 or 3 letters pre-fix) :

8

Namespacing and File naming

Page 9: AngularJS Best Practices

• Controllers : ScheduleCtrl

• Services : ScheduleSvc

• Filters : RatingFilter

• Directives : small-schedule

• Partials :

– if my controller is ScheduleCtrl ScheduleCtrl.html

– If my directives is small-schedule small-schedule.html

9

Namespacing and File naming

Page 10: AngularJS Best Practices

10

Understanding Modules

Page 11: AngularJS Best Practices

• Modules have nothing to do with object naming (so far…)

• The Injector has the list of all the objects in our application

• Only one injector exists in eachAngular application

11

Understanding ModulesModules

Page 12: AngularJS Best Practices

• One Module

+ it's the simplest option by far

you don't have to worry about how your module organization reflects the organization of your files and folders, and you still only need to deliver the code you want running in the browser.

- if you have code that you are sharing amongst several applications, then they all need to have the same module name.

- delivering code as a third party or publishing it to the open source community is not really a possibility.

12

Organizing modules

Page 13: AngularJS Best Practices

• Two Modules

One for code custom to the current application, and one for any shared code.

+ simplicity

- increased complexity, and some rigidity when sharing or publishing code.

This strategy works best if you will be building multiple applications that may share some code, or if you intend to publish a portion of your code to third parties, or you plan to open source it, say a library of widgets.

13

Organizing modules

Page 14: AngularJS Best Practices

• MainModule with several sub-modules

The MainModule may or may not have any actual objects in it, it might just be a collection of sub-modules.

+ you have tons of organization for your code

Modules become an extra way to organize and deliver just the parts of your application that you want to deliver.

- increased complexity of managing those different modules.

- build system will have to be more complex as well14

Organizing modules

Page 15: AngularJS Best Practices

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

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

var serviceApp = angular.module('serviceApp', ['servicesA‘, 'servicesB']);

15

MainModule with several sub-modulesExample

Page 16: AngularJS Best Practices

• removing all unnecessary whitespace

• rename variables and parameters to short names.

Problem : Angular uses reflection to look at parameter names of certain functions like controllers and services, so that its dependency injector can provide the correct dependency

angular.module('app').controller('Controller1',function($scope, mySvc) {$scope.val = mySvc.val;

})

.NET bundling

angular.module('app').controller('Controller1',function(a, b) {a.val = b.val;

})

16

Minification

Page 17: AngularJS Best Practices

• Node solution : ng-min

• Our solution : classic .net bundling on fly

Constraints , we need to write that way:

angular.module('app').controller('Controller1',

['$scope','mySvc', function($scope, mySvc) { $scope.val = mySvc.val;}])

I

17

Minification

Page 18: AngularJS Best Practices

• Controllers

– setup the scope

– view interaction

• Services

– handle non-view logic

– communicate with the server

– hold data & state (not the only one)

– DOM manipulation (code smell ;))

– Business

• Directives

– Manipulate DOM

– Receive View Events

18

Definitions and roles

• Views

– Display the application

– Declare bindings & directives

Page 19: AngularJS Best Practices

• coordinate View and Model

Nothing else, the ctrl shouldn’t knwon the business logic or the model structure

angular.module('app').controller('scheduleCtrl',function($scope, schedule) {

$scope.schedule = schedule;

$scope.register = function(newClass) {

$scope.schedule.register(newClass);

}

});

• Limited # of collaborators

split the ctrl in smaller ones

Facade pattern

• Testable 19

Controllers – Design guidelines

Page 20: AngularJS Best Practices

A service is treated as a singleton, that is there is only one instance of a specific service available during the whole lifetime of the Angular application. This is different from e.g. a controller of which many instances can be created.

app.service(‘registration’, function() {

return {

title: ‘Service from Service’

}

});

But in Angular there are actually sevral ways to create a service

20

Services - creation

Page 21: AngularJS Best Practices

app.value(‘myValService’, ‘someValue’);

What the value function does is create a service that is exactly what you passed into the value function.

We can define any string, number, date-time, array or object as a value. We can even register a function as a value

This could be things like the full name of the user, it’s role and so on. Typically we would load this data after the user has successfully logged into the system and keep this data around as long as the user remains logged in.

Dependancy Injection is not possible.

21

Services –value

Page 22: AngularJS Best Practices

The constant function is essentially the same as the value function, except it's available during the app configuration phase.

app.constant(‘myValService’, ‘someValue’);

The difference between a value and a constant service is that the former can only be injected (and thus be used) in a service or a controller while the latter can also be injected into a module configuration function..

Dependancy Injection is not possible.

22

Services – constant

Page 23: AngularJS Best Practices

Example

app.constant(‘myValService’, ‘someValue’);

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

app.config(function ($provide) {

$provide.constant('movieTitle', 'The Matrix');

});

app.controller('ctrl', function (movieTitle) {

expect(movieTitle).toEqual('The Matrix');

});

23

Services – constant

Page 24: AngularJS Best Practices

The purpose of the factory function is to generate the single object, or function, that represents the service to the rest of the application.

app.factory('profile', function() {

return {

"name": "Anonymous",

"Id": null,

"login": function(){…},

"logout": function(){…}

}

});

So the factory function is simply just the normal way to create a service.

Notice that the factory function can ask for other dependencies.

24

Services - factory

Page 25: AngularJS Best Practices

The service function is a lot like the factory function with one difference.

The service function will take the function you give it and call new on it. Then it will cache the result of that function and give you the result every time you ask for that service.

monApp.service('profile', function() {

this.name = "Anonymous";

this.id = null;

this.login = function(){…}

this.logout = function(){…}

});

« return » isn’t required.

Generally factory is all you need. No question regarding the “this” !25

Services - service

Page 26: AngularJS Best Practices

This function is ultimately what all those other functions use under the covers.

This allows you to create a service from a much lower level.

What you have to do is give the provider function another function whose return value must have a $get function.

A provider is actually a configurable factory. The provider accepts an object or a constructor.

The benefit here is that using provider, you have the option to make your service configurable and configure it before it is created.

Offical Reco :

You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.

26

Services - provider

Page 27: AngularJS Best Practices

angular.module('app').controller('scheduleCtrl',function($scope, registration) {

$scope.title = registration.title;

});

app.config(function($provide) {

$provide.provider('registration', function() {

var type;

return {

setType: function(value) {

type = value;

},

$get: function() {

return {

title: 'Service from Provider ' + type

}

} } })})

app.config(function(registrationProvider) {

registrationProvider.setType('Angular');

})27

Services - provider

Page 28: AngularJS Best Practices

A decorator can modify or encapsulate other providers. There is one exception and that a constant cannot be decorated

28

Services - Decorator

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

app.value('movieTitle', 'The Matrix');

app.config(function ($provide) {$provide.decorator('movieTitle', function ($delegate) {return $delegate + ' - starring Keanu Reeves';

});});

app.controller('myController', function (movieTitle) {expect(movieTitle).toEqual('The Matrix - starring Keanu Reeves');

});

Page 29: AngularJS Best Practices

Filters are really just a service with a specific kind of name.

29

Services – filters as services

app.factory("ratingsFilter", function() {return function(input) {

var rating = parseInt(input);var result = "";for(var i=0; i < rating; i++) {

result += "*";}return result;

}});

app.filter("ratings", function() {return function(input) {

var rating = parseInt(input);var result = "";for(var i=0; i < rating; i++) {

result += "*";}return result;

}});

Page 30: AngularJS Best Practices

• SRP : single responsability !

• Cohesive : having all the functionality of an object relate to the primary purpose of the object

• Loosely Coupled : A good service should be loosely coupled to any dependencies that it has.

• Good interface : Any situation where you call multiple methods to do a single job is less effective.

• Testable

30

Services – Design Guidelines

Page 31: AngularJS Best Practices

function Course(title, instructorIds, id) {

this.title = title;

this.instructorIds = instructorIds;

this.id = id;

}

Course.prototype.displayName = function() {

// code

}

app.value('courseFactory', {

createCourse: function(title, credits, department, instructors) {

var instructorIds = [];

for(var i=0; i < instructors.length; i++) {

instructorIds.push(instructors[i].id);

}

return new Course(title, instructorIds, -1);

}

})31

Services - Specific Types - Factories

Page 32: AngularJS Best Practices

app.value('schedule', {

classes: [],

addClass: function(newClass) {

for(var i=0; i < this.classes.length; i++) {

if(this.classes[i] === newClass) {

return;

}

}

this.classes.push(newClass);

},

dropClass: function(classToDrop) {

for(var i=0; i < this.classes.length; i++) {

if(this.classes[i] === classToDrop) {

this.classes.splice(i, 1);

}

}

}

})32

Services - Specific Types - Stateful Singletons

Page 33: AngularJS Best Practices

app.value('grades', []);

app.value('calculateGPA', function(grades) {

// implementation

return "4.0";

})

app.controller('userCtrl',function($scope, grades, calculateGPA) {

$scope.GPA = calculateGPA(grades);

});

33

Services - Specific Types - Functions

Page 34: AngularJS Best Practices

• Services

Syntax: module.service( 'serviceName', function );Result: When declaring serviceName as an injectable argument you will be provided with an instance of the function. In other words new FunctionYouPassedToService().

• Factories

Syntax: module.factory( 'factoryName', function );Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory.

• Providers

Syntax: module.provider( 'providerName', function );Result: When declaring providerName as an injectable argument you will be provided with ProviderFunction().$get(). The constructor function is instantiated before the $get method is called - ProviderFunction is the function reference passed to module.provider. 34

Services - Summary

Page 35: AngularJS Best Practices

• Purposes of directives

piece of visible display that may or not be reusable, but whose functionality is encapsulated and an interface provided so that the widget can easily represent a piece of display and functionality of your app

• Classic Error :

In The javascript : myDirective (CamelCase)

In the view : my-directive (snake case)

First thing to check in case of error : check the names

• Naming Convention: prefix : bc/bcsp ?

A directive should be unique because Ajs doesn’t override, but stack.

35

Directives

Page 36: AngularJS Best Practices

JS:

app.directive(‘bcHelloWorld', function() {

return {

restrict: 'E',

replace: 'true',

template: '<h3>Hello World!!</h3>'

};

});

Html:

<bc-hello-world/>

36

Directives

Page 37: AngularJS Best Practices

• restrict: 'E' => Element : <date-picker></date-picker>

• restrict: ‘A' => Attributes: <input type="text" date-picker/>

• restrict: 'C' => class : <input type="text" class="date-picker"/>

• restrict: 'M' => comment : <!--directive:date-picker-->

Combine possible, for example : restrict: 'AE‘

Html5 compliant : <input type="text" data-date-picker/>

37

Directives - restrict

Page 38: AngularJS Best Practices

• Template : inline

• TemplateUrl : path to html file

38

Directives – template / templateUrl

Page 39: AngularJS Best Practices

True :

<h3>Hello World!!</h3>

False:

<hello-world><h3>Hello World!!</h3></hello-world>

39

Directives – replace

Page 40: AngularJS Best Practices

app.directive('helloWorld', function() {

return {

restrict: 'AE',

replace: true,

template: '<p style="background-color:{{color}}">Hello World',

link: function(scope, elem, attrs) {

elem.bind('click', function() {

elem.css('background-color', 'white');

scope.$apply(function() {

scope.color = "white";

});

});

elem.bind('mouseover', function() {

elem.css('cursor', 'pointer');

});

}

};

});

40

Directives – Link

Page 41: AngularJS Best Practices

It takes three arguments:

• scope – The scope passed to the directive. In this case it’s the same as the parent controller scope.

• elem – The jQLite (a subset of jQuery) wrapped element on which the directive is applied. If you have included jQuery in the HTML before AngularJS is included, this becomes jQuery wrapped instead of jQLite. As the element is already wrapped with jQuery/jQLite, there is no need to again wrap it inside $() for DOM manipulations.

• attrs – An object representing normalized attributes attached to the element on which the directive is applied. For example, you can attach attributes in HTML like: <hello-world some-attribute></hello-world> and access it in the link function as attrs.someAttribute.

41

Directives – Link

Page 42: AngularJS Best Practices

return {

restrict:'E',

require: 'nameOfSiblingController'

}

Ability to require in a controller from another directive,

Return null if the required isn’t here.

Require on parent :

return {

restrict:'E',

require: '^nameOfParentController'

}

42

Directives – Require

Page 43: AngularJS Best Practices

2 solutions :

• put the functionality into the link function of the directive

• create a controller and put that functionality into the controller (can be no inline to reuse it)

controller: function($scope) {

$scope.viewClassDetails = function(classToView) {

// do something

console.log('viewing details for ' + classToView.name);

}

<=>

link: function(scope) {

scope.viewClassDetails = function(classToView) {

// do something

console.log('viewing details for ' + classToView.name);

}

}43

Directives - Controllers vs Link

Page 44: AngularJS Best Practices

Ask yourself “when do I want my code to run?”

Before compilation? – Controller

After compilation? – Link

Never condone putting DOM manipulation in an angular controller

“Am I just doing template and scope things?” – goes into controller

“Am I adding some coolbeans jquery library?” – goes in link

http://jasonmore.net/angular-js-directives-difference-controller-link/

44

Directives - Controllers vs Link

Page 45: AngularJS Best Practices

there are 3 ways for a directive to interface with a containing scope:

1. share the scope

2. create an inherited scope

3. create an isolated scope

1&2 : the directive simply has access to all the objects in the containing scope

Stop !!!! What is the scope ??

45

Directives - interfaces

Page 46: AngularJS Best Practices

In Angular, the scope is the magic. All binding happens through a scope, all interaction happens through a scope.

very important to understand

Help to debug : chrome extension « AngularJS Batarang »

1. on top i have the root scope / ng-app correspond to the root scope

2. all scopes belong to exactly 1 Element

3. 1 scope <=> 1 ng-controller

46

Scope - Dealing with scope

Page 47: AngularJS Best Practices

47

Scope - Dealing with scope

Page 48: AngularJS Best Practices

• By default

48

Scope - Sharing scope

Page 49: AngularJS Best Practices

app.directive('scInstructorCount', function() {

return {

scope: true,

link: function(scope) {

scope.instructorList.push({id:4, name: 'Professor Lockhart'});

scope.CurrentInstructorId = 22;

}

}

});

Example : only the directive see the CurrentInstructorId49

Scope - inherited scope

Page 50: AngularJS Best Practices

WARING EASY BUG !!

how do you correctly bind an ngModel to a parent scope item

=> make sure there is a dot in the binding

50

Scope - inherited scope

Page 51: AngularJS Best Practices

app.directive('scInstructorCount', function() {

return {

restrict: 'A',

replace: true,

templateUrl: 'scInstructorCount.html',

scope: {

instructorList: '=',

title: '='

},

link: function(scope) {

scope.title = "My New Title";

}

}

});

<div sc-instructor-count instructor-list="instructorList" title="title" sc-new-instructor></div>

51

Scope - Isolating scope

WARNING snake-case / camel-

case

Two way binding !

Page 52: AngularJS Best Practices

+ : easy

- : hidden dependencies

- : put things in the parent useless for him, here only for the childs

52

Communicating between componentsCommunicating with Inherited Scopes

Page 53: AngularJS Best Practices

• Use global bus:

$rootScope.$broadcast("course:registered", course);

$scope.$on('course:registered', function(event, course) {

$scope.notify('You have registered for ' + course.name);

})

+ : logic, responsability inside the ctrl

- : add $rootscope to every listeners, a listener could cancel the event

- : warning to the string name of the event

53

Communicating between componentsCommunicating with Events

Page 54: AngularJS Best Practices

A service is a singleton so it’s the same for every body.

+ : business logic is in the right place

- : more set-up work

- : difficult to draw the line between display logic and business logic

54

Communicating between componentsCommunicating with Services

Page 55: AngularJS Best Practices

I see dead brackets !!!!

It happen more for classic website, not for SPA.

Solution 1: ngCloak

Need to add style in css :

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {display: none !important;

}

We add the directive ngCloak on the place we want to hide before the binding ( not too high, to not display too much white space)

55

Avoiding FOUCFlash of Unstyled Content

Page 56: AngularJS Best Practices

Solution 2: ngBind

<h1>{{name}}</h1>

<h1 ng-bind="name">&nbsp;</h1>

But we still have a problem with ng-hide, which hide nothing until the binding,

56

Avoiding FOUCFlash of Unstyled Content

Page 57: AngularJS Best Practices

Solution 3: Waiting image

<img src="spinner.gif" ng-hide="ready" style="width:400px" />

<div ng-cloak ng-show="ready" class="jumbotron">..</div>

The « ready » variable is set to true when the data are loaded,

57

Avoiding FOUCFlash of Unstyled Content

Page 58: AngularJS Best Practices

old way : write Html, write Jquery to manipulate the DOM

Angular Way:

• Put declarative View Logic in the View

• Don't put imperative logic in the view

imperative code belongs in the controller, declarative code belongs in the view

Thinking about how to do something with the view might lead us down the wrong road

Thinking declaratively,what we want to do is represent our state in our controller and then get the view to manipulate itself based on that state.

The controler should not take control of the view but the view should listen to the scope !

clean code.58

Thinking Declaratively

Page 59: AngularJS Best Practices

create custom HTML through directives

not only powerful, it is truly paradigm changing when it comes to web development

your HTML turn a low-level description of the layout of a web page into a domain-specific language that describes the functionality of your application

Primary type to object !

HTML not only technic, it has to be readable !

59

Directives as a DSL

Page 60: AngularJS Best Practices

• Inline controllers (only js)

• Controllers and ngInclude (html)

• Directives (js + html)

60

Breaking Down A Page into Components

Page 61: AngularJS Best Practices

• Manage deferred tasks (e.g. asynchronous tasks)

• Methods

– then(successCallback, errorCallback, notifyCallback): callback for successfullyresolved promise, callback for error (optional), and notify (optionnal, see« deferred »)

– catch(errorCallback): callback for error

– finally(callback): callback for either success or error but with no data modification (?)

• Promises can be chained.

61

Promises

Page 62: AngularJS Best Practices

• Creates and manipulates a promise

• Methods:

– resolve(value): ends the promise (success) with the given value

– reject(reason): same but with an error

– notify(value): updates promise without ending it

• Promise : property that gives the associated promise object

• $q (injectable)

– create a deferred object: $q.defer()

– Method “all”: Use to combine multiple promises into a single one (resolved when all promises are resolved; rejected when any promise is rejected),

62

Deferred

Page 63: AngularJS Best Practices

• Factory AngularJS to interact with RESTful APIs

• Module: ‘ngResource’

• Basic usage:

• Returns object with defaults methods:

{

'get': {method:'GET'},

'save': {method:'POST'},

'query': {method:'GET', isArray:true},

'remove': {method:'DELETE'},

'delete': {method:'DELETE'}

}

• Possible to add custom methods with options (url, HTTP method, cache, …)

63

$resource

Page 64: AngularJS Best Practices

• Get the resource: myResource.get({userId: 1234})

• $resource “magic object”: Calling a $resource method returns immediately an empty response object. That object will be filled when the response is received.

• This object has also a $promise property which is a promise that will be resolved when the response arrives

• So both usages are possible:

– $scope.myResources = myResource.get(…); => Simple. The view will display returned data when it’s available.

– myResource.get(…).$promise().then([success], [error]); => More advanced. Manage loader image, errors, …

64

$resource (2)

Page 65: AngularJS Best Practices

• It’s an AngularJs service that simplifies requesting a RESTful API.

• No $resource bugs (?)

• It supports all HTTP methods.

• It supports self-linking elements

• It uses promises, instead of $resource ‘s “magic object”.

– But there is still a “magic object” available (“$object” property) ;-)

• Possible to extends API results (extendModel and extendCollection)

• Configuration (global and/or by service)

– setBaseUrl

– setDefaultHttpFields

– Response/request interceptors

– etc

65

RestAngular

Page 66: AngularJS Best Practices

• Web API exemple: http://myapi/accounts/45/buildings/1234

• Using RestAngular :

– Restangular.all('accounts') => “/accounts” route – No request sent

– Restangular.all('accounts').getList() => Request the API and returns a promise for the list.

– Restangular.one('accounts', 1234) => “/accounts/1234” route – No request sent

– Restangular.one('accounts', 1234).get() => Request the API and returns a promise for the element.

– Restangular.one('accounts', 123).one('buildings', 456).get() => Chaining methods to get that element (“/accounts/123/buildings/456”)

• It’s also possible to call a specific URL: Restangular.allUrl('searches', 'http://google.com/‘);

66

RestAngular (2)

Page 67: AngularJS Best Practices

• same template for all js file:

(function (undefined) {

'use strict';

})();

include in the great SideWaffle visual studio extension : http://sidewaffle.com/

Here this the JavaScript IIFE template.

• use JS Hint with Web Essentials for visual studio (http://vswebessentials.com/features/javascript) and customize the settings with the json provided at the end of this document.

check your messages in error list !

67

Betclic Best practices - Javascript

Page 68: AngularJS Best Practices

• never create variable to get the module :

avoid :

var app = angular.module("sportWebApp");

app.controller('watheverCtrl')....

recommended :

angular.module("sportWebApp").controller('watheverCtrl')....

• directive convention :

use replace true

use E for templating

use A for behavior

never use Class or Comment

always use data-xxx to pass param to an isolated scope

W3C ! 68

Betclic Best practices - AngularJs coding

Page 69: AngularJS Best Practices

• use $inject , to remove the [] inline

• use named functions instead of passing anonymous function to get cleaner code, better readability, easier debug and reduces the nested callback code

.controller('myCtrl',['$scope','toto',function ($scope,toto){

....

}])

.controller('myCtrl',myCtrl);

myCtrl.$inject=['$scope','toto'];

function myCtrl($scope,toto){

....

}69

Betclic Best practices - AngularJs coding

Page 70: AngularJS Best Practices

• add comments for each js file , with this template

/**

* @desc [un casing name] that [display/filter/use for] [functionality detail]

* @file [file name (no path)]

* @example [example of using in html for directive/filter or in js for service]

*/

70

Betclic Best practices - AngularJs coding

Page 71: AngularJS Best Practices

• naming convention :

controller :

file name : xxxCtrl.js

object name : xxxCtrl

service :

file name : xxxSvc.js

object name : xxxSvc

directive :

file name : [domaine/page prefix]xxxCtrl.js

object name : bcsp[domaine/page prefix]xxxx

(bcsp stand for betclic sport)

example : evtCompetitionHeaderDir.js / bcspEvtCompetitionHeader

using in the html example :

<bcsp-evt-competition-header></bcsp-evt-competition-header> 71

Betclic Best practices - Naming , solution organization

Page 72: AngularJS Best Practices

• 'shared' folder at the root of the 'app' : all the common directives, service, filters etc ...

[domaine/page prefix] is here the full name, ex : market/marketDir.js

• Mirror the app to an app folder in the unit test project

a xxx.js file in the web app should have a xxxTest.js file in the Test project.

• Single Responsibility , Rule of 1: Define 1 component per file.

• Directives, Limit 1 Per File: Create one directive per file. Name the file for the directive.

72

Betclic Best practices - Naming , solution organization

Page 73: AngularJS Best Practices

73

Conclusion

Page 74: AngularJS Best Practices
Page 75: AngularJS Best Practices

• http://blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/

• http://www.synbioz.com/blog/la_creation_de_service_avec_angularjs

• http://www.frangular.com/2012/12/differentes-facons-de-creer-un-service-angularjs.html

• http://lostechies.com/gabrielschenker/2014/02/26/angular-jspart-13-services/

• http://stackoverflow.com/questions/15666048/angular-js-service-vs-provider-vs-factory

• http://sametmax.com/service-factory-et-provider-dans-angularjs/

• http://www.johnpapa.net/angular-style-guide/

75

Reference Services

Page 76: AngularJS Best Practices

• http://mgonto.github.io/restangular-talk-with-image-right/#28

• http://www.ng-newsletter.com/posts/restangular.html

• http://ath3nd.wordpress.com/2013/08/05/15/

• https://github.com/mgonto/restangular

• http://ath3nd.wordpress.com/2013/08/05/15/

76

Restangular

Page 77: AngularJS Best Practices

• Settings recommended :

77

.jshintrc

Page 78: AngularJS Best Practices

Find out more

• On https://techblog.betclicgroup.com/

Page 79: AngularJS Best Practices

We want our Sports betting, Poker, Horseracing and Casino & Games brands to be easyto use for every gamer around the world.Code with us to make that happen.

Look at all the challenges we offer HERE

We are hiring !

Check our Employer Page

Follow us on LinkedIn

Page 80: AngularJS Best Practices

About Us• Betclic Everest Group, one of the world leaders in online

gaming, has a unique portfolio comprising variouscomplementary international brands: Betclic, Everest,Bet-at-home.com, Expekt, Monte-Carlo Casino…

• Through our brands, Betclic Everest Group placesexpertise, technological know-how and security at theheart of our strategy to deliver an on-line gaming offerattuned to the passion of our players. We want ourbrands to be easy to use for every gamer around theworld. We’re building our company to make that happen.

• Active in 100 countries with more than 12 millioncustomers worldwide, the Group is committed topromoting secure and responsible gaming and is amember of several international professional associationsincluding the EGBA (European Gaming and BettingAssociation) and the ESSA (European Sports SecurityAssociation).