├── dist └── .gitkeep ├── tests ├── output │ └── .gitkeep ├── unit │ ├── filter │ │ ├── filter.controller.spec.js │ │ └── filter.filter.spec.js │ ├── service │ │ ├── service.controller.spec.js │ │ └── service.service.spec.js │ ├── directives │ │ └── directives.controller.directive.spec.js │ ├── controller │ │ └── service.controller.spec.js │ └── promise │ │ ├── promise.service.spec.js │ │ └── promise.controller.spec.js └── e2e │ ├── home.spec.js │ ├── examples │ ├── view.spec.js │ ├── error.spec.js │ ├── controller.spec.js │ ├── filter.spec.js │ ├── directives.spec.js │ ├── promise.spec.js │ └── service.spec.js │ └── core.spec.js ├── server ├── routes.js └── server.js ├── app ├── images │ └── favicon.ico ├── examples │ ├── directives │ │ ├── directives.simple.directive.tpl.html │ │ ├── directives.module.js │ │ ├── directives.controller.directive.tpl.html │ │ ├── directives.simple.directive.js │ │ ├── directives.route.js │ │ ├── directives.controller.directive.js │ │ └── directives.tpl.html │ ├── view │ │ ├── view.module.js │ │ ├── view.tpl.html │ │ └── view.route.js │ ├── error │ │ ├── error.module.js │ │ ├── error.tpl.html │ │ └── error.route.js │ ├── filter │ │ ├── filter.module.js │ │ ├── filter.filter.js │ │ ├── filter.controller.js │ │ ├── filter.route.js │ │ └── filter.tpl.html │ ├── promise │ │ ├── promise.module.js │ │ ├── promise.service.js │ │ ├── promise.route.js │ │ ├── promise.tpl.html │ │ └── promise.controller.js │ ├── service │ │ ├── service.module.js │ │ ├── service.controller.js │ │ ├── service.service.js │ │ ├── service.route.js │ │ └── service.tpl.html │ └── controller │ │ ├── controller.module.js │ │ ├── controller.tpl.html │ │ ├── controller.route.js │ │ └── controller.controller.js ├── home │ ├── home.module.js │ ├── home.route.js │ └── home.tpl.html ├── core │ ├── core.module.js │ └── core.nav.controller.js ├── styles │ └── style.css ├── app.js └── index.html ├── gulpfile.js ├── .gitignore ├── protractor.conf.js ├── .jshintrc ├── bower.json ├── package.json ├── karma.conf.js └── README.md /dist/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/output/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/routes.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app) { 2 | 3 | }; 4 | -------------------------------------------------------------------------------- /app/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkern/angular-best-practice/HEAD/app/images/favicon.ico -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // all gulp tasks are located in the ./build/tasks directory 2 | // gulp configuration is in files in ./build/config directory 3 | require("require-dir")("build/tasks"); 4 | -------------------------------------------------------------------------------- /app/examples/directives/directives.simple.directive.tpl.html: -------------------------------------------------------------------------------- 1 |
2 |4 | -------------------------------------------------------------------------------- /app/home/home.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.home", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/view/view.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.view", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/error/error.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.error", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/filter/filter.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.filter", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/promise/promise.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.promise", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/service/service.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.service", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/controller/controller.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.controller", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/examples/directives/directives.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.directives", [ 4 | // every module has 'practice.core' as dependency 5 | "practice.core" 6 | ]); 7 | })(); 8 | -------------------------------------------------------------------------------- /app/core/core.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | angular.module("practice.core", [ 4 | // default dependencies for all other modules 5 | // who got 'practice.core' as dependency goes here 6 | "ui.router" 7 | ]); 8 | })(); 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # temp files, logs & reports 2 | tests/output/karma-result.xml 3 | 4 | # gulp generated distributions 5 | /dist/development 6 | /dist/productive 7 | 8 | # dependencies 9 | node_modules/ 10 | bower_components/ 11 | 12 | # system files 13 | Thumbs.db 14 | .DS_Store 15 | 16 | # ide 17 | .idea 18 | 19 | # psydo standard to track empty directories 20 | !.gitkeep 21 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | // address of the selenium server 3 | seleniumAddress: "http://localhost:4444/wd/hub", 4 | 5 | // file pattern to match e2e tests 6 | specs: ["tests/e2e/**/*.spec.js"], 7 | 8 | // base url where angular application is reachable 9 | baseUrl: "http://localhost:1337/", 10 | 11 | // browsers to start by protractor 12 | capabilities: { 13 | 'browserName': 'chrome' 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /app/styles/style.css: -------------------------------------------------------------------------------- 1 | html * { outline: none !important; } 2 | h1 { margin-bottom: 25px; } 3 | ul { margin-bottom: 0; } 4 | section.content { padding-top: 65px; } 5 | footer { margin-top: -15px; font-size: .9em; } 6 | .panel-body h2 { margin-top: 40px; } 7 | .panel-body h2:first-of-type { margin-top: 0; } 8 | .panel-body ul { list-style: square inside; padding: 0; } 9 | -------------------------------------------------------------------------------- /tests/unit/filter/filter.controller.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("when using filter controller", function() 4 | { 5 | var controller; 6 | 7 | beforeEach(module("practice.filter")); 8 | beforeEach(inject(function($controller) { 9 | controller = $controller("practice.filterController"); 10 | })); 11 | 12 | it("should have at least one text entry", function() { 13 | expect(controller.entries.length).toBeGreaterThan(0); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /app/examples/directives/directives.controller.directive.tpl.html: -------------------------------------------------------------------------------- 1 |This is the output of
3 |<simple-directive></simple-directive>.
2 |11 | -------------------------------------------------------------------------------- /tests/e2e/home.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("serving the home page", function() { 4 | beforeEach(function() { 5 | browser.get("#/"); 6 | }); 7 | 8 | it("should have a headline h1", function() { 9 | var h1 = element(by.css("h1")); 10 | expect(h1.getText()).not.toBe(""); 11 | }); 12 | 13 | it("should have at least one content box", function() { 14 | var panel = element.all(by.css(".panel .panel-body")); 15 | expect(panel.count()).toBeGreaterThan(0); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/e2e/examples/view.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("serving the view page", function() { 4 | beforeEach(function() { 5 | browser.get("#/view"); 6 | }); 7 | 8 | it("should have a headline h1", function() { 9 | var h1 = element(by.css("h1")); 10 | expect(h1.getText()).not.toBe(""); 11 | }); 12 | 13 | it("should have at least one content box", function() { 14 | var panel = element.all(by.css(".panel .panel-body")); 15 | expect(panel.count()).toBeGreaterThan(0); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/e2e/examples/error.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("serving the error page", function() { 4 | beforeEach(function() { 5 | browser.get("#/error"); 6 | }); 7 | 8 | it("should have a headline h1", function() { 9 | var h1 = element(by.css("h1")); 10 | expect(h1.getText()).not.toBe(""); 11 | }); 12 | 13 | it("should have at least one content box", function() { 14 | var panel = element.all(by.css(".panel .panel-body")); 15 | expect(panel.count()).toBeGreaterThan(0); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | angular.module("practice", [ 4 | // make every module this app uses available here 5 | 6 | // partials module - configured and generated in gulpfile.js 7 | "practice.partials", 8 | 9 | // home screen module 10 | "practice.home", 11 | 12 | // example modules 13 | "practice.controller", 14 | "practice.directives", 15 | "practice.error", 16 | "practice.filter", 17 | "practice.promise", 18 | "practice.service", 19 | "practice.view" 20 | ]); 21 | }()); 22 | -------------------------------------------------------------------------------- /tests/unit/service/service.controller.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("when using service controller", function() 4 | { 5 | var controller; 6 | 7 | beforeEach(module("practice.service")); 8 | beforeEach(inject(function($controller) { 9 | controller = $controller("practice.serviceController", { practiceService: "service" }); 10 | })); 11 | 12 | it("should register service correctly", function() { 13 | expect(controller.service).toBe("service"); 14 | }); 15 | 16 | it("should have a message", function() { 17 | expect(controller.message).toBeDefined(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /app/examples/service/service.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | angular.module("practice.service") 4 | .controller("practice.serviceController", serviceController); 5 | 6 | // always use $inject to make functions minify-able 7 | // @see https://docs.angularjs.org/guide/di 8 | serviceController.$inject = ["practiceService"]; 9 | 10 | function serviceController(practiceService) { 11 | var self = this; 12 | 13 | // define public variables for own scope 14 | self.service = practiceService; 15 | self.message = "used practiceService.verboseMessage(message) ..."; 16 | } 17 | }()); 18 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globalstrict": true, 3 | "validthis": true, 4 | "browser" : true, 5 | "browserify" : true, 6 | "devel" : true, 7 | "jquery": true, 8 | "jasmine": true, 9 | "node" : true, 10 | "shelljs" : true, 11 | "globals": { 12 | "console": true, 13 | "__dirname": true, 14 | "require": true, 15 | "angular": false, 16 | "describe": false, 17 | "it": false, 18 | "xdescribe": false, 19 | "xit": false, 20 | "expect": false, 21 | "beforeEach": false, 22 | "afterEach": false, 23 | "module": false, 24 | "inject": false, 25 | "process": true, 26 | "by": true, 27 | "browser": true, 28 | "element": true, 29 | "Buffer": true 30 | } 31 | } -------------------------------------------------------------------------------- /app/examples/filter/filter.filter.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | angular.module("practice.filter") 4 | .filter("startsWith", startsWith); 5 | 6 | function startsWith() { 7 | // a filter is always a function with two parameters 'input' and 'expression' 8 | // and will return the filtered input again, in this case an array list 9 | // @see https://docs.angularjs.org/api/ng/filter/filter 10 | return function(list, expression) { 11 | return list.filter(function(entry) { 12 | if( !expression ) { 13 | return true; 14 | } 15 | 16 | return entry.name.toLowerCase().substr(0, expression.length) === expression.toLowerCase(); 17 | }); 18 | }; 19 | } 20 | }()); 21 | -------------------------------------------------------------------------------- /tests/unit/service/service.service.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("when using the practiceService", function() 4 | { 5 | var practiceService; 6 | 7 | beforeEach(module("practice.service")); 8 | beforeEach(inject(function($injector) { 9 | practiceService = $injector.get("practiceService"); 10 | spyOn(window, "alert"); 11 | })); 12 | 13 | it("should alert 'used practiceService.publicFunction ...'", function() { 14 | practiceService.publicFunction(); 15 | expect(window.alert).toHaveBeenCalledWith("used practiceService.publicFunction ..."); 16 | }); 17 | 18 | it("should alert 'test message'", function() { 19 | practiceService.verboseMessage("test message"); 20 | expect(window.alert).toHaveBeenCalledWith("test message"); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /app/examples/error/error.tpl.html: -------------------------------------------------------------------------------- 1 |This is the output of
3 |<controller-directive exchange="data" format="dd.MM.yyyy"></controller-directive>.4 | 5 |6 |7 | Formatted current date by given format string: 8 | {{controller.date|date:controller.format}} 9 |
10 |
This module enable Angular to redirect any unknown routing to /error, like a '404 - Not Found' page.
app/examples/error/
error.module.js
14 | - module creation
15 | error.route.js
18 | - template routing
19 | error.tpl.html
22 | - content template
23 | This example creates a simple view with custom url route.
6 |In result it will route #/view to template examples/view/view.tpl.html.
app/examples/view/
view.module.js
15 | - module creation
16 | view.route.js
19 | - template routing
20 | view.tpl.html
23 | - content template
24 | This example creates a view-controller pair with custom url route.
6 |
7 | In result it will route #/controller to template examples/controller/controller.tpl.html
8 | and receive most of it's displayed information from the controller and delivers a content function action() for the button below.
9 |
{{controller.location}}
{{file.name}}
25 | - {{file.description}}
26 | This example creates a simple promise names usePromise inside the promiseService service.
Promises enables you to react on .then() and .catch() inside your app.
10 | Trigger the promise by the buttons below.
11 | Choose to let them success (resolve) or fail (reject).
12 |
app/examples/promises/
promises.module.js
23 | - module creation
24 | promises.route.js
27 | - template routing
28 | promises.controller.js
31 | - view controller
32 | promises.service.js
35 | - service creation
36 | promises.tpl.html
39 | - content template
40 | This example creates a simple filter named startsWith, e.g. usable by ng-repeat.
Try filter the list below by typing in something.
9 |Results: {{result.length}}
14 |app/examples/filter/
filter.module.js
29 | - module creation
30 | filter.route.js
33 | - template routing
34 | filter.filter.js
37 | - filter creation
38 | filter.tpl.html
41 | - content template
42 | This example creates a simple service named practiceService with two public functions publicFunction and verboseMessage.
9 | Trigger the service function by buttons below. 10 | Type in a custom message to demonstrate passing parameters. 11 |
12 |app/examples/service/
service.module.js
26 | - module creation
27 | service.route.js
30 | - template routing
31 | service.controller.js
34 | - view controller
35 | service.service.js
38 | - service creation
39 | service.tpl.html
42 | - content template
43 | It contains some examples of angular components and their best practice usages.
6 | 7 |9 | There are some projects and persons out there, defining some pseudo standards using angular. 10 | I'll adapted their ideas and created this project to combine everything for me and others. 11 | Feel free to let me know if you got some better ideas. :) 12 |
13 |Inspirations:
14 |This example creates a two directives simpleDirective and controllerDirective.
The results of this directives can be seen below.
7 | 8 |The simple-directive just display a template without any further actions.
14 | The controller-directive has an own controller, like a view-controller.
15 | Beside this the directive exchanges data between itself and the parent view.
16 | Just type something in the input field below ...
17 |
app/examples/directives/
directives.module.js
30 | - module creation
31 | directives.route.js
34 | - template routing
35 | directives.tpl.html
38 | - content template
39 | directives.simple.directive.js
42 | - simple directive creation
43 | directives.simple.directive.tpl.html
46 | - simple directive template
47 | directives.controller.directive.js
50 | - controller directive creation
51 | directives.controller.directive.tpl.html
54 | - controller directive template
55 |