From 10257e8905ce1bce8c2173e35865b228c77f255a Mon Sep 17 00:00:00 2001 From: toubou91 Date: Sat, 11 Jun 2016 18:32:58 +0200 Subject: [PATCH 1/4] Started translating to greek --- README-gr-gr.md | 847 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 847 insertions(+) create mode 100644 README-gr-gr.md diff --git a/README-gr-gr.md b/README-gr-gr.md new file mode 100644 index 0000000..b475eb2 --- /dev/null +++ b/README-gr-gr.md @@ -0,0 +1,847 @@ +# Εισαγωγή + +Ο σκοπός αυτού του style guide είναι να παρουσιάσει ένα σύνολο από best practices και style guidelines, για μια εφαρμογή AngularJS. Τα εν λόγω best practices έχουν συλλεχθεί από τις παρακάτω πηγές: + +0. AngularJS source code +0. Source code από άρθρα που διάβασα +0. Προσωπική εμπειρία + +**Σημείωση 1**: ακόμη και τώρα, αυτό το έργο είναι μια πρόχειρη εκδοχή του style guide και κύριος σκοπός του είναι να γίνει community-driven. Συνεπώς, οποιαδήποτε προσθήκη κρίνεται απαραίτητη από τον αναγνώστη, είναι ευπρόσδεκτη από όλη την κοινότητα. + +**Σημείωση 2**: πρωτού ακολουθήσετε οποιαδήποτε από τα guidelines στις μεταφράσεις του αγγλικού κειμένου, επιβεβαιώστε ότι είναι ενημερωμένα. Η τελευταία έκδοση του AngularJS style guide βρίσκεται στο παρόν έγγραφο. + +Αυτό το style guide δεν παρέχει κοινότυπα guidelines που αφορούν τον προγραμματισμό σε JavaScript. Αυτά μπορούν να βρεθούν στους παρακάτω συνδέσμους: + +0. [Google's JavaScript style guide](https://google.github.io/styleguide/javascriptguide.xml) +0. [Mozilla's JavaScript style guide](https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style) +0. [GitHub's JavaScript style guide](https://github.com/styleguide/javascript) +0. [Douglas Crockford's JavaScript style guide](http://javascript.crockford.com/code.html) +0. [Airbnb JavaScript style guide](https://github.com/airbnb/javascript) +0. [Idiomatic JavaScript style guide](https://github.com/rwaldron/idiomatic.js/) + +Για προγραμματισμό σε AngularJS συστήνεται το [Google's JavaScript style guide](https://google.github.io/styleguide/javascriptguide.xml). + +Υπάρχει επίσης παρόμοιο κεφάλαιο στο GitHub wiki του AngularJS, από τον [ProLoser](https://github.com/ProLoser). Μπορείτε να το δείτε [εδώ](https://github.com/angular/angular.js/wiki). + +# Μεταφράσεις + +- [Γερμανικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-de-de.md) +- [Ισπανικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-es-es.md) +- [Γαλλικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-fr-fr.md) +- [Ινδονησιακά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-id-id.md) +- [Ιταλικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-it-it.md) +- [Ιαπωνικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-ja-jp.md) +- [Κορεάτικα](https://github.com/mgechev/angularjs-style-guide/blob/master/README-ko-kr.md) +- [Πολωνικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-pl-pl.md) +- [Πορτογαλικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-pt-br.md) +- [Ρωσικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-ru-ru.md) +- [Σέρβικα](https://github.com/mgechev/angularjs-style-guide/blob/master/README-sr.md) +- [Serbian lat](https://github.com/mgechev/angularjs-style-guide/blob/master/README-sr-lat.md) +- [Κινέζικα](https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md) +- [Τουρκικά](https://github.com/mgechev/angularjs-style-guide/blob/master/README-tr-tr.md) + +# Πίνακας περιεχομένων +* [Γενικά](#γενικά) + * [Directory structure](#directory-structure) + * [Markup](#markup) + * [Naming conventions](#naming-conventions) + * [Others](#others) +* [Modules](#modules) +* [Controllers](#controllers) +* [Directives](#directives) +* [Filters](#filters) +* [Services](#services) +* [Templates](#templates) +* [Routing](#routing) +* [E2E Testing](#e2e-testing) +* [i18n](#i18n) +* [Performance](#performance) +* [Contribution](#contribution) +* [Contributors](#contributors) + +# General + +## Directory structure + +Since a large AngularJS application has many components it's best to structure it in a directory hierarchy. +There are two main approaches: + +* Creating high-level divisions by component types and lower-level divisions by functionality. + +In this way the directory structure will look like: + +``` +. +├── app +│   ├── app.js +│   ├── controllers +│   │   ├── home +│   │   │   ├── FirstCtrl.js +│   │   │   └── FirstCtrl.spec.js +│   │   │   └── SecondCtrl.js +│   │   │   └── SecondCtrl.spec.js +│   │   └── about +│   │   └── ThirdCtrl.js +│   │   └── ThirdCtrl.spec.js +│   ├── directives +│   │   ├── home +│   │   │   └── directive1.js +│   │   │   └── directive1.spec.js +│   │   └── about +│   │   ├── directive2.js +│   │   ├── directive2.spec.js +│   │   └── directive3.js +│   │   └── directive3.spec.js +│   ├── filters +│   │   ├── home +│   │   └── about +│   └── services +│   ├── CommonService.js +│   ├── CommonService.spec.js +│   ├── cache +│   │   ├── Cache1.js +│   │   ├── Cache1.spec.js +│   │   └── Cache2.js +│   │   └── Cache2.spec.js +│   └── models +│   ├── Model1.spec.js +│   ├── Model1.js +│   └── Model2.spec.js +│   └── Model2.js +├── partials +├── lib +└── e2e-tests +``` + +* Creating high-level divisions by functionality and lower-level divisions by component types. + +Here is its layout: + +``` +. +├── app +│   ├── app.js +│   ├── common +│   │   ├── controllers +│   │   ├── directives +│   │   ├── filters +│   │   └── services +│   ├── home +│   │   ├── controllers +│   │   │   ├── FirstCtrl.js +│   │   │   ├── FirstCtrl.spec.js +│   │   │   └── SecondCtrl.js +│   │   │   └── SecondCtrl.spec.js +│   │   ├── directives +│   │   │   └── directive1.js +│   │   │   └── directive1.spec.js +│   │   ├── filters +│   │   │   ├── filter1.js +│   │   │   ├── filter1.spec.js +│   │   │   └── filter2.js +│   │   │   └── filter2.spec.js +│   │   └── services +│   │   ├── service1.js +│   │   ├── service1.spec.js +│   │   └── service2.js +│   │   └── service2.spec.js +│   └── about +│   ├── controllers +│   │   └── ThirdCtrl.js +│   │   └── ThirdCtrl.spec.js +│   ├── directives +│   │   ├── directive2.js +│   │   ├── directive2.spec.js +│   │   └── directive3.js +│   │   └── directive3.spec.js +│   ├── filters +│   │   └── filter3.js +│   │   └── filter3.spec.js +│   └── services +│   └── service3.js +│   └── service3.spec.js +├── partials +├── lib +└── e2e-tests +``` + +* In case the directory name contains multiple words, use lisp-case syntax: + +``` +app + ├── app.js + └── my-complex-module +    ├── controllers +    ├── directives +    ├── filters +    └── services +``` + +* Put all the files associated with the given directive (i.e. templates, CSS/SASS files, JavaScript) in a single folder. If you choose to use this style be consistent and use it everywhere along your project. + +``` +app +└── directives + ├── directive1 + │   ├── directive1.html + │   ├── directive1.js + │   ├── directive1.spec.js + │   └── directive1.sass + └── directive2 + ├── directive2.html + ├── directive2.js + ├── directive2.spec.js + └── directive2.sass +``` + +This approach can be combined with both directory structures above. +* The unit tests for a given component (`*.spec.js`) should be located in the directory where the component is. This way when you make changes to a given component finding its test is easy. The tests also act as documentation and show use cases. + +``` +services +├── cache +│   ├── cache1.js +│   └── cache1.spec.js +└── models + ├── model1.js + └── model1.spec.js +``` + +* The `app.js` file should contain route definitions, configuration and/or manual bootstrap (if required). +* Each JavaScript file should only hold **a single component**. The file should be named with the component's name. +* Use AngularJS project structure template like [Yeoman](http://yeoman.io), [ng-boilerplate](http://ngbp.github.io/ngbp/#/home). + +Conventions about component naming can be found in each component section. + +## Markup + +[TLDR;](http://developer.yahoo.com/blogs/ydn/high-performance-sites-rule-6-move-scripts-bottom-7200.html) Put the scripts at the bottom. + +```html + + + + + MyApp + + +
+
+
+ + + + +``` + +Keep things simple and put AngularJS specific directives after standard attributes. This will make it easier to skim your code and will make it easier to maintain because your attributes are consistently grouped and positioned. + +```html +
+
+ +
+
+``` + +Other HTML attributes should follow the Code Guide's [recommendation](http://mdo.github.io/code-guide/#html-attribute-order) + +## Naming conventions +The following table is shown the naming conventions for every element: + +Element | Naming style | Example | usage +----|------|----|-------- +Modules | lowerCamelCase | angularApp | +Controllers | Functionality + 'Ctrl' | AdminCtrl | +Directives | lowerCamelCase | userInfo | +Filters | lowerCamelCase | userFilter | +Services | UpperCamelCase | User | constructor +Factories | lowerCamelCase | dataFactory | others + +## Others + +* Use: + * `$timeout` instead of `setTimeout` + * `$interval` instead of `setInterval` + * `$window` instead of `window` + * `$document` instead of `document` + * `$http` instead of `$.ajax` + * `$location` instead of `window.location` or `$window.location` + * `$cookies` instead of `document.cookie` + +This will make your testing easier and in some cases prevent unexpected behaviour (for example, if you missed `$scope.$apply` in `setTimeout`). + +* Automate your workflow using tools like: + * [NPM](https://www.npmjs.com/) + * [Grunt](http://gruntjs.com) + * [Gulp](http://gulpjs.com) + * [Yeoman](http://yeoman.io) + * [Bower](http://bower.io) + + +* Use promises (`$q`) instead of callbacks. It will make your code look more elegant and clean, and save you from callback hell. +* Use `$resource` instead of `$http` when possible. The higher level of abstraction will save you from redundancy. +* Use an AngularJS pre-minifier ([ng-annotate](https://github.com/olov/ng-annotate)) for preventing problems after minification. +* Don't use globals. Resolve all dependencies using Dependency Injection, this will prevent bugs and monkey patching when testing. +* Avoid globals by using Grunt/Gulp to wrap your code in Immediately Invoked Function Expression (IIFE). You can use plugins like [grunt-wrap](https://www.npmjs.com/package/grunt-wrap) or [gulp-wrap](https://www.npmjs.com/package/gulp-wrap/) for this purpose. Example (using Gulp) + + ```Javascript + gulp.src("./src/*.js") + .pipe(wrap('(function(){\n"use strict";\n<%= contents %>\n})();')) + .pipe(gulp.dest("./dist")); + ``` +* Do not pollute your `$scope`. Only add functions and variables that are being used in the templates. +* Prefer the usage of [controllers instead of `ngInit`](https://github.com/angular/angular.js/commit/010d9b6853a9d2718b095e4c017c9bd5f135e0b0). There are only a few appropriate uses of ngInit, such as for aliasing special properties of ngRepeat, and for injecting data via server side scripting. Besides these few cases, you should use controllers rather than ngInit to initialize values on a scope. The expression passed to `ngInit` should go through lexing, parsing and evaluation by the Angular interpreter implemented inside the `$parse` service. This leads to: + - Performance impact, because the interpreter is implemented in JavaScript + - The caching of the parsed expressions inside the `$parse` service doesn't make a lot of sense in most cases, since `ngInit` expressions are often evaluated only once + - Is error-prone, since you're writing strings inside your templates, there's no syntax highlighting and further support by your editor + - No run-time errors are thrown +* Do not use `$` prefix for the names of variables, properties and methods. This prefix is reserved for AngularJS usage. +* Do not use `JQUERY` inside your app, If you must, use `JQLite` instead with `angular.element`. +* When resolving dependencies through the DI mechanism of AngularJS, sort the dependencies by their type - the built-in AngularJS dependencies should be first, followed by your custom ones: + +```javascript +module.factory('Service', function ($rootScope, $timeout, MyCustomDependency1, MyCustomDependency2) { + return { + //Something + }; +}); +``` + +# Modules + +* Modules should be named with lowerCamelCase. For indicating that module `b` is submodule of module `a` you can nest them by using namespacing like: `a.b`. + + There are two common ways for structuring the modules: + + 0. By functionality + 0. By component type + + Currently there's not a big difference, but the first way looks cleaner. Also, if lazy-loading modules is implemented (currently not in the AngularJS roadmap), it will improve the app's performance. + +# Controllers + +* Do not manipulate DOM in your controllers, this will make your controllers harder for testing and will violate the [Separation of Concerns principle](https://en.wikipedia.org/wiki/Separation_of_concerns). Use directives instead. +* The naming of the controller is done using the controller's functionality (for example shopping cart, homepage, admin panel) and the substring `Ctrl` in the end. +* Controllers are plain javascript [constructors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor), so they will be named UpperCamelCase (`HomePageCtrl`, `ShoppingCartCtrl`, `AdminPanelCtrl`, etc.). +* The controllers should not be defined as globals (even though AngularJS allows this, it is a bad practice to pollute the global namespace). +* Use the following syntax for defining controllers: + + ```JavaScript + function MyCtrl(dependency1, dependency2, ..., dependencyn) { + // ... + } + module.controller('MyCtrl', MyCtrl); + ``` + + In order to prevent problems with minification, you can automatically generate the array definition syntax from the standard one using tools like [ng-annotate](https://github.com/olov/ng-annotate) (and grunt task [grunt-ng-annotate](https://github.com/mzgol/grunt-ng-annotate)). + + Another alternative will be to use `$inject` like: + + ```JavaScript + angular + .module('app') + .controller('Homepage', Homepage); + + Homepage.$inject = ['$log', '$http', 'ngRoute']; + + function Homepage($log, $http, ngRoute) { + // ... + } + ``` + +* Avoid use of `$scope` service to define functions and properties as part of controllers. Use `$scope` only if It's really needed: + 0. For publish and subscribe to events: `$scope.$emit`, `$scope.$broadcast`, and `$scope.$on`. + 0. For _watch_ values or collections: `$scope.$watch`, `$scope.$watchCollection` + +* Prefer using `controller as` syntax and capture `this` using a variable: + + ```html +
+ {{ main.things }} +
+ ``` + + ```JavaScript + app.controller('MainCtrl', MainCtrl); + MainCtrl.$inject = ['$http']; + + function MainCtrl ($http) { + var vm = this; + //a clearer visual connection on how is defined on the view + vm.title = 'Some title'; + vm.description = 'Some description'; + + $http.get('/api/main/things').then(function (response) { + vm.things = response.data.things; // Adding 'things' as a property of the controller + }); + } + ``` + + Avoid using `this` keyword repeatedly inside a controller: + + ```JavaScript + app.controller('MainCtrl', MainCtrl); + MainCtrl.$inject = ['$http']; + + // Avoid + function MainCtrl ($http) { + this.title = 'Some title'; + this.description = 'Some description'; + + $http.get('/api/main/things').then(function (response) { + // Warning! 'this' is in a different context here. + // The property will not be added as part of the controller context + this.things = response.data.things; + }); + } + ``` + + Using a consistent and short variable name is preferred, for example `vm`. + + The main benefits of using this syntax: + * Creates an 'isolated' component - binded properties are not part of `$scope` prototype chain. This is good practice since `$scope` prototype inheritance has some major drawbacks (this is probably the reason it was removed on Angular 2): + * It is hard to track where data is coming from. + * Scope's value changes can affect places you did not intend to affect. + * Harder to refactor. + * The '[dot rule](http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html)'. + * Removes the use of `$scope` when no need for special operations (as mentioned above). This is a good preparation for AngularJS V2. + * Syntax is closer to that of a 'vanilla' JavaScript constructor + + Digging more into `controller as`: [digging-into-angulars-controller-as-syntax](http://toddmotto.com/digging-into-angulars-controller-as-syntax/) +* If using array definition syntax, use the original names of the controller's dependencies. This will help you produce more readable code: + + ```JavaScript + function MyCtrl(l, h) { + // ... + } + + module.controller('MyCtrl', ['$log', '$http', MyCtrl]); + ``` + + which is less readable than: + + ```JavaScript + function MyCtrl($log, $http) { + // ... + } + + module.controller('MyCtrl', ['$log', '$http', MyCtrl]); + ``` + + This especially applies to a file that has so much code that you'd need to scroll through. This would possibly cause you to forget which variable is tied to which dependency. + +* Make the controllers as lean as possible. Abstract commonly used functions into a service. +* Avoid writing business logic inside controllers. Delegate business logic to a `model`, using a service. + For example: + + ```Javascript + //This is a common behaviour (bad example) of using business logic inside a controller. + angular.module('Store', []) + .controller('OrderCtrl', function () { + var vm = this; + + vm.items = []; + + vm.addToOrder = function (item) { + vm.items.push(item);//-->Business logic inside controller + }; + + vm.removeFromOrder = function (item) { + vm.items.splice(vm.items.indexOf(item), 1);//-->Business logic inside controller + }; + + vm.totalPrice = function () { + return vm.items.reduce(function (memo, item) { + return memo + (item.qty * item.price);//-->Business logic inside controller + }, 0); + }; + }); + ``` + + When delegating business logic into a 'model' service, controller will look like this (see 'use services as your Model' for service-model implementation): + + ```Javascript + // order is used as a 'model' + angular.module('Store', []) + .controller('OrderCtrl', function (order) { + var vm = this; + + vm.items = order.items; + + vm.addToOrder = function (item) { + order.addToOrder(item); + }; + + vm.removeFromOrder = function (item) { + order.removeFromOrder(item); + }; + + vm.totalPrice = function () { + return order.total(); + }; + }); + ``` + + Why business logic / app state inside controllers is bad? + * Controllers instantiated for each view and dies when the view unloads + * Controllers are not reusable - they are coupled with the view + * Controllers are not meant to be injected + + +* Communicate within different controllers using method invocation (possible when a child wants to communicate with its parent) or `$emit`, `$broadcast` and `$on` methods. The emitted and broadcasted messages should be kept to a minimum. +* Make a list of all messages which are passed using `$emit`, `$broadcast` and manage it carefully because of name collisions and possible bugs. + + Example: + + ```JavaScript + // app.js + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + Custom events: + - 'authorization-message' - description of the message + - { user, role, action } - data format + - user - a string, which contains the username + - role - an ID of the role the user has + - action - specific action the user tries to perform + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + ``` + +* When you need to format data encapsulate the formatting logic into a [filter](#filters) and declare it as dependency: + + ```JavaScript + function myFormat() { + return function () { + // ... + }; + } + module.filter('myFormat', myFormat); + + function MyCtrl($scope, myFormatFilter) { + // ... + } + + module.controller('MyCtrl', MyCtrl); + ``` +* In case of nested controllers use "nested scoping" (the `controllerAs` syntax): + + **app.js** + ```javascript + module.config(function ($routeProvider) { + $routeProvider + .when('/route', { + templateUrl: 'partials/template.html', + controller: 'HomeCtrl', + controllerAs: 'home' + }); + }); + ``` + **HomeCtrl** + ```javascript + function HomeCtrl() { + var vm = this; + + vm.bindingValue = 42; + } + ``` + **template.html** + ```html +
+ ``` + +# Directives + +* Name your directives with lowerCamelCase. +* Use `scope` instead of `$scope` in your link function. In the compile, post/pre link functions you have already defined arguments which will be passed when the function is invoked, you won't be able to change them using DI. This style is also used in AngularJS's source code. +* Use custom prefixes for your directives to prevent name collisions with third-party libraries. +* Do not use `ng` or `ui` prefixes since they are reserved for AngularJS and AngularJS UI usage. +* DOM manipulations must be done only through directives. +* Create an isolated scope when you develop reusable components. +* Use directives as attributes or elements instead of comments or classes, this will make your code more readable. +* Use `scope.$on('$destroy', fn)` for cleaning up. This is especially useful when you're wrapping third-party plugins as directives. +* Do not forget to use `$sce` when you should deal with untrusted content. + +# Filters + +* Name your filters with lowerCamelCase. +* Make your filters as light as possible. They are called often during the `$digest` loop so creating a slow filter will slow down your app. +* Do a single thing in your filters, keep them coherent. More complex manipulations can be achieved by piping existing filters. + +# Services + +This section includes information about the service component in AngularJS. It is not dependent of the way of definition (i.e. as provider, `.factory`, `.service`), except if explicitly mentioned. + +* Use camelCase to name your services. + * UpperCamelCase (PascalCase) for naming your services, used as constructor functions i.e.: + + ```JavaScript + function MainCtrl(User) { + var vm = this; + vm.user = new User('foo', 42); + } + + module.controller('MainCtrl', MainCtrl); + + function User(name, age) { + this.name = name; + this.age = age; + } + + module.factory('User', function () { + return User; + }); + ``` + + * lowerCamelCase for all other services. + +* Encapsulate all the business logic in services. Prefer using it as your `model`. For example: + ```Javascript + // order is the 'model' + angular.module('Store') + .factory('order', function () { + var add = function (item) { + this.items.push (item); + }; + + var remove = function (item) { + if (this.items.indexOf(item) > -1) { + this.items.splice(this.items.indexOf(item), 1); + } + }; + + var total = function () { + return this.items.reduce(function (memo, item) { + return memo + (item.qty * item.price); + }, 0); + }; + + return { + items: [], + addToOrder: add, + removeFromOrder: remove, + totalPrice: total + }; + }); + ``` + + See 'Avoid writing business logic inside controllers' for an example of a controller consuming this service. +* Services representing the domain preferably a `service` instead of a `factory`. In this way we can take advantage of the "klassical" inheritance easier: + + ```JavaScript + function Human() { + //body + } + Human.prototype.talk = function () { + return "I'm talking"; + }; + + function Developer() { + //body + } + Developer.prototype = Object.create(Human.prototype); + Developer.prototype.code = function () { + return "I'm coding"; + }; + + myModule.service('human', Human); + myModule.service('developer', Developer); + + ``` + +* For session-level cache you can use `$cacheFactory`. This should be used to cache results from requests or heavy computations. +* If given service requires configuration define the service as provider and configure it in the `config` callback like: + + ```JavaScript + angular.module('demo', []) + .config(function ($provide) { + $provide.provider('sample', function () { + var foo = 42; + return { + setFoo: function (f) { + foo = f; + }, + $get: function () { + return { + foo: foo + }; + } + }; + }); + }); + + var demo = angular.module('demo'); + + demo.config(function (sampleProvider) { + sampleProvider.setFoo(41); + }); + ``` + +# Templates + +* Use `ng-bind` or `ng-cloak` instead of simple `{{ }}` to prevent flashing content. +* Avoid writing complex expressions in the templates. +* When you need to set the `src` of an image dynamically use `ng-src` instead of `src` with `{{ }}` template. +* When you need to set the `href` of an anchor tag dynamically use `ng-href` instead of `href` with `{{ }}` template. +* Instead of using scope variable as string and using it with `style` attribute with `{{ }}`, use the directive `ng-style` with object-like parameters and scope variables as values: + +```html +
+
my beautifully styled div which will work in IE
; +
+``` + +```JavaScript + angular + .module('app') + .controller('MainCtrl', MainCtrl); + + MainCtrl.$inject = []; + + function MainCtrl() { + var vm = this; + vm.divStyle = { + width: 200, + position: 'relative' + }; + } +``` + +# Routing + +* Use `resolve` to resolve dependencies before the view is shown. +* Do not place explicit RESTful calls inside the `resolve` callback. Isolate all the requests inside appropriate services. This way you can enable caching and follow the separation of concerns principle. + +# E2E Testing + +E2E tests are the next common sense step after unit tests, that will allow you to trace bugs and errors in the behaviour of your system. They are great for providing a sanity check that most common scenarios of using your application works. This way you can automate the process and run it each time before you deploy your application. + +Ideally, Angular End-to-End tests are written in Jasmine. These tests are run using the Protractor E2E test runner which uses native events and has special features for Angular applications. + +File structure: + +``` +. +├── app +│   ├── app.js +│   ├── home +│   │   ├── home.html +│   │   ├── controllers +│   │   │   ├── FirstCtrl.js +│   │   │   ├── FirstCtrl.spec.js +│   │   ├── directives +│   │   │   └── directive1.js +│   │   │   └── directive1.spec.js +│   │   ├── filters +│   │   │   ├── filter1.js +│   │   │   └── filter1.spec.js +│   │   └── services +│   │   ├── service1.js +│   │   └── service1.spec.js +│   └── about +│   ├── about.html +│   ├── controllers +│   │   └── ThirdCtrl.js +│   │   └── ThirdCtrl.spec.js +│   └── directives +│      ├── directive2.js +│      └── directive2.spec.js +├── partials +├── lib +└── e2e-tests + ├── protractor.conf.js + └── specs + ├── home.js + └── about.js +``` + +# i18n + +* For newer versions of the framework (>=1.4.0) use the built-in i18n tools, when using older versions (<1.4.0) use [`angular-translate`](https://github.com/angular-translate/angular-translate). + +# Performance + +* Optimize the digest cycle + + * Watch only the most vital variables. When required to invoke the `$digest` loop explicitly (it should happen only in exceptional cases), invoke it only when required (for example: when using real-time communication, don't cause a `$digest` loop in each received message). + * For content that is initialized only once and then never changed, use single-time watchers like [`bindonce`](https://github.com/Pasvaz/bindonce) for older versions of AngularJS or one-time bindings in AngularJS >=1.3.0. + ```html +
+ {{ ::main.things }} +
+ ``` + or + ```html +
+ ``` + After that, **no** watchers will be created for `main.things` and any changes of `main.things` will not update the view. + * Make the computations in `$watch` as simple as possible. Making heavy and slow computations in a single `$watch` will slow down the whole application (the `$digest` loop is done in a single thread because of the single-threaded nature of JavaScript). + * When watching collections, do not watch them deeply when not strongly required. Better use `$watchCollection`, which performs a shallow check for equality of the result of the watched expression and the previous value of the expression's evaluation. + * Set third parameter in `$timeout` function to false to skip the `$digest` loop when no watched variables are impacted by the invocation of the `$timeout` callback function. + * When dealing with big collections, which change rarely, [use immutable data structures](http://blog.mgechev.com/2015/03/02/immutability-in-angularjs-immutablejs). + + +* Consider decreasing number of network requests by bundling/caching html template files into your main javascript file, using [grunt-html2js](https://github.com/karlgoldstein/grunt-html2js) / [gulp-html2js](https://github.com/fraserxu/gulp-html2js). See [here](http://ng-learn.org/2014/08/Populating_template_cache_with_html2js/) and [here](http://slides.com/yanivefraim-1/real-world-angularjs#/34) for details. This is particularly useful when the project has a lot of small html templates that can be a part of the main (minified and gzipped) javascript file. + +# Contribution + +Since the goal of this style guide is to be community-driven, contributions are greatly appreciated. +For example, you can contribute by extending the Testing section or by translating the style guide to your language. + +# Contributors + +[mgechev](https://github.com/mgechev) |[morizotter](https://github.com/morizotter) |[chatii2412](https://github.com/chatii2412) |[pascalockert](https://github.com/pascalockert) |[yanivefraim](https://github.com/yanivefraim) |[ericguirbal](https://github.com/ericguirbal) | +:---: |:---: |:---: |:---: |:---: |:---: | +[mgechev](https://github.com/mgechev) |[morizotter](https://github.com/morizotter) |[chatii2412](https://github.com/chatii2412) |[pascalockert](https://github.com/pascalockert) |[yanivefraim](https://github.com/yanivefraim) |[ericguirbal](https://github.com/ericguirbal) | + +[agnislav](https://github.com/agnislav) |[ray7551](https://github.com/ray7551) |[mainyaa](https://github.com/mainyaa) |[LeonardCModoran](https://github.com/LeonardCModoran) |[elfinxx](https://github.com/elfinxx) |[Xuefeng-Zhu](https://github.com/Xuefeng-Zhu) | +:---: |:---: |:---: |:---: |:---: |:---: | +[agnislav](https://github.com/agnislav) |[ray7551](https://github.com/ray7551) |[mainyaa](https://github.com/mainyaa) |[LeonardCModoran](https://github.com/LeonardCModoran) |[elfinxx](https://github.com/elfinxx) |[Xuefeng-Zhu](https://github.com/Xuefeng-Zhu) | + +[rubystream](https://github.com/rubystream) |[lukaszklis](https://github.com/lukaszklis) |[susieyy](https://github.com/susieyy) |[SullyP](https://github.com/SullyP) |[giacomocusinato](https://github.com/giacomocusinato) |[cironunes](https://github.com/cironunes) | +:---: |:---: |:---: |:---: |:---: |:---: | +[rubystream](https://github.com/rubystream) |[lukaszklis](https://github.com/lukaszklis) |[susieyy](https://github.com/susieyy) |[SullyP](https://github.com/SullyP) |[giacomocusinato](https://github.com/giacomocusinato) |[cironunes](https://github.com/cironunes) | + +[guiltry](https://github.com/guiltry) |[MertSKaan](https://github.com/MertSKaan) |[mingchen](https://github.com/mingchen) |[tornad](https://github.com/tornad) |[cavarzan](https://github.com/cavarzan) |[jmblog](https://github.com/jmblog) | +:---: |:---: |:---: |:---: |:---: |:---: | +[guiltry](https://github.com/guiltry) |[MertSKaan](https://github.com/MertSKaan) |[mingchen](https://github.com/mingchen) |[tornad](https://github.com/tornad) |[cavarzan](https://github.com/cavarzan) |[jmblog](https://github.com/jmblog) | + +[luixaviles](https://github.com/luixaviles) |[kuzzmi](https://github.com/kuzzmi) |[andreasonny83](https://github.com/andreasonny83) |[tiagobarreto](https://github.com/tiagobarreto) |[nktssh](https://github.com/nktssh) |[clbn](https://github.com/clbn) | +:---: |:---: |:---: |:---: |:---: |:---: | +[luixaviles](https://github.com/luixaviles) |[kuzzmi](https://github.com/kuzzmi) |[andreasonny83](https://github.com/andreasonny83) |[tiagobarreto](https://github.com/tiagobarreto) |[nktssh](https://github.com/nktssh) |[clbn](https://github.com/clbn) | + +[atodorov](https://github.com/atodorov) |[dreame4](https://github.com/dreame4) |[apetro](https://github.com/apetro) |[valgreens](https://github.com/valgreens) |[meetbryce](https://github.com/meetbryce) |[unseen1980](https://github.com/unseen1980) | +:---: |:---: |:---: |:---: |:---: |:---: | +[atodorov](https://github.com/atodorov) |[dreame4](https://github.com/dreame4) |[apetro](https://github.com/apetro) |[valgreens](https://github.com/valgreens) |[meetbryce](https://github.com/meetbryce) |[unseen1980](https://github.com/unseen1980) | + +[cminhho](https://github.com/cminhho) |[dwmkerr](https://github.com/dwmkerr) |[dchest](https://github.com/dchest) |[kuzmeig1](https://github.com/kuzmeig1) |[gsamokovarov](https://github.com/gsamokovarov) |[grvcoelho](https://github.com/grvcoelho) | +:---: |:---: |:---: |:---: |:---: |:---: | +[cminhho](https://github.com/cminhho) |[dwmkerr](https://github.com/dwmkerr) |[dchest](https://github.com/dchest) |[kuzmeig1](https://github.com/kuzmeig1) |[gsamokovarov](https://github.com/gsamokovarov) |[grvcoelho](https://github.com/grvcoelho) | + +[yassirh](https://github.com/yassirh) |[bargaorobalo](https://github.com/bargaorobalo) |[hermankan](https://github.com/hermankan) |[jabhishek](https://github.com/jabhishek) |[jesselpalmer](https://github.com/jesselpalmer) |[capaj](https://github.com/capaj) | +:---: |:---: |:---: |:---: |:---: |:---: | +[yassirh](https://github.com/yassirh) |[bargaorobalo](https://github.com/bargaorobalo) |[hermankan](https://github.com/hermankan) |[jabhishek](https://github.com/jabhishek) |[jesselpalmer](https://github.com/jesselpalmer) |[capaj](https://github.com/capaj) | + +[johnnyghost](https://github.com/johnnyghost) |[jordanyee](https://github.com/jordanyee) |[whoan](https://github.com/whoan) |[nacyot](https://github.com/nacyot) |[mariolamacchia](https://github.com/mariolamacchia) |[mischkl](https://github.com/mischkl) | +:---: |:---: |:---: |:---: |:---: |:---: | +[johnnyghost](https://github.com/johnnyghost) |[jordanyee](https://github.com/jordanyee) |[whoan](https://github.com/whoan) |[nacyot](https://github.com/nacyot) |[mariolamacchia](https://github.com/mariolamacchia) |[mischkl](https://github.com/mischkl) | + +[michaelmov](https://github.com/michaelmov) |[kirstein](https://github.com/kirstein) |[mo-gr](https://github.com/mo-gr) |[mortonfox](https://github.com/mortonfox) |[cryptojuice](https://github.com/cryptojuice) |[astalker](https://github.com/astalker) | +:---: |:---: |:---: |:---: |:---: |:---: | +[michaelmov](https://github.com/michaelmov) |[kirstein](https://github.com/kirstein) |[mo-gr](https://github.com/mo-gr) |[mortonfox](https://github.com/mortonfox) |[cryptojuice](https://github.com/cryptojuice) |[astalker](https://github.com/astalker) | + +[qwerfrewq](https://github.com/qwerfrewq) |[olov](https://github.com/olov) |[vorktanamobay](https://github.com/vorktanamobay) |[sahat](https://github.com/sahat) |[smelukov](https://github.com/smelukov) |[ganchiku](https://github.com/ganchiku) | +:---: |:---: |:---: |:---: |:---: |:---: | +[qwerfrewq](https://github.com/qwerfrewq) |[olov](https://github.com/olov) |[vorktanamobay](https://github.com/vorktanamobay) |[sahat](https://github.com/sahat) |[smelukov](https://github.com/smelukov) |[ganchiku](https://github.com/ganchiku) | + +[kaneshin](https://github.com/kaneshin) |[imaimiami](https://github.com/imaimiami) |[dooart](https://github.com/dooart) |[thomastuts](https://github.com/thomastuts) |[UrielMiranda](https://github.com/UrielMiranda) |[vkarampinis](https://github.com/vkarampinis) | +:---: |:---: |:---: |:---: |:---: |:---: | +[kaneshin](https://github.com/kaneshin) |[imaimiami](https://github.com/imaimiami) |[dooart](https://github.com/dooart) |[thomastuts](https://github.com/thomastuts) |[UrielMiranda](https://github.com/UrielMiranda) |[vkarampinis](https://github.com/vkarampinis) | + +[VladimirKazan](https://github.com/VladimirKazan) |[andela-abankole](https://github.com/andela-abankole) |[grapswiz](https://github.com/grapswiz) |[coderhaoxin](https://github.com/coderhaoxin) |[giantray](https://github.com/giantray) |[ntaoo](https://github.com/ntaoo) | +:---: |:---: |:---: |:---: |:---: |:---: | +[VladimirKazan](https://github.com/VladimirKazan) |[andela-abankole](https://github.com/andela-abankole) |[grapswiz](https://github.com/grapswiz) |[coderhaoxin](https://github.com/coderhaoxin) |[giantray](https://github.com/giantray) |[ntaoo](https://github.com/ntaoo) | + +[dominickolbe](https://github.com/dominickolbe) | +:---: | +[dominickolbe](https://github.com/dominickolbe) | + + From e391d02177067c5228a4fa856964ce2490fe7f11 Mon Sep 17 00:00:00 2001 From: Thodoris Bais Date: Wed, 9 Aug 2017 23:39:23 +0200 Subject: [PATCH 2/4] Update README-gr-gr.md --- README-gr-gr.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README-gr-gr.md b/README-gr-gr.md index b475eb2..38dd76f 100644 --- a/README-gr-gr.md +++ b/README-gr-gr.md @@ -55,20 +55,20 @@ * [Routing](#routing) * [E2E Testing](#e2e-testing) * [i18n](#i18n) -* [Performance](#performance) -* [Contribution](#contribution) -* [Contributors](#contributors) +* [Απόδοση](#απόδοση) +* [Συνεισφορά](#συνεισφορά) +* [Συνεισφέροντες](#συνεισφέροντες) -# General +# Γενικά -## Directory structure +## Δομή καταλόγου -Since a large AngularJS application has many components it's best to structure it in a directory hierarchy. -There are two main approaches: +Το AngularJS έχει πολλά components, οπότε είναι καλύτερο να το δομήσετε σε ιεραρχία καταλόγου. +Υπάρχουν δύο κύριες προσεγγίσεις: -* Creating high-level divisions by component types and lower-level divisions by functionality. +* Δημιουργία κατηγοριν υψηλού επιπέδου βάσει τύπου component και κατηγοριών χαμηλότερου επιπέδου βσει λειτουργικότητας. -In this way the directory structure will look like: +Με αυτό τον τρόπο η δομή καταλόγου θα φαίνεται σαν: ``` . @@ -113,9 +113,9 @@ In this way the directory structure will look like: └── e2e-tests ``` -* Creating high-level divisions by functionality and lower-level divisions by component types. +* Δημιουργώντας κατηγορίες υψηλού επιπέδου βάσει λειτουργικότητας και κατηγορίες χαμηλότερου επιπέδου βάσει τύπου component. -Here is its layout: +Εδώ φαίνεται η διάταξή του: ``` . @@ -165,7 +165,7 @@ Here is its layout: └── e2e-tests ``` -* In case the directory name contains multiple words, use lisp-case syntax: +* Σε περίπτωση που το όνομα του καταλόγου περιέχει πολλς λέξεις, χρησιμοποιήστε σύνταξη lisp-case: ``` app From 0d0bb056e87ebbc4c1e52be751ebcb5b6953e358 Mon Sep 17 00:00:00 2001 From: Thodoris Bais Date: Thu, 10 Aug 2017 22:01:12 +0200 Subject: [PATCH 3/4] Update README-gr-gr.md --- README-gr-gr.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README-gr-gr.md b/README-gr-gr.md index 38dd76f..45520a3 100644 --- a/README-gr-gr.md +++ b/README-gr-gr.md @@ -177,7 +177,7 @@ app    └── services ``` -* Put all the files associated with the given directive (i.e. templates, CSS/SASS files, JavaScript) in a single folder. If you choose to use this style be consistent and use it everywhere along your project. +* Βάλτε όλα τα αρχεία που σχετίζονται με το εκάστοτε directive (π.χ. templates, αρχεία CSS/SASS, JavaScript) σε ένα φάκελο. Εάν διαλέξετε να χρησιμοποιήσετε αυτό το στυλ, να είστε σταθεροί και να κάνετε χρήση του παντού στο πρότζεκτ σας. ``` app @@ -194,8 +194,8 @@ app └── directive2.sass ``` -This approach can be combined with both directory structures above. -* The unit tests for a given component (`*.spec.js`) should be located in the directory where the component is. This way when you make changes to a given component finding its test is easy. The tests also act as documentation and show use cases. +Αυτή η προσέγγιση μπορεί να συνδυαστεί και με τις δύο προαναφερθείσες δομές καταλόγου. +* Τα unit tests για ένα δοθέν component (`*.spec.js`) πρέπει να βρίσκονται στον κατάλογο που βρίσκεται και το ίδιο το component. Κατ'αυτό τον τρόπο, όταν κάνετε αλλαγές στο εκάστοτε component, μπορείτε εύκολα να βρείτε το τεστάκι που αντιστοιχε σε αυτό. Τα τεστάκια, επίσης, δρουν και ως documentation και παρουσιάζουν τα use cases. ``` services @@ -207,15 +207,15 @@ services └── model1.spec.js ``` -* The `app.js` file should contain route definitions, configuration and/or manual bootstrap (if required). -* Each JavaScript file should only hold **a single component**. The file should be named with the component's name. -* Use AngularJS project structure template like [Yeoman](http://yeoman.io), [ng-boilerplate](http://ngbp.github.io/ngbp/#/home). +* Το αρχείο `app.js` πρέπει να περιλαμβάνει ορισμούς των route , configuration και/ή manual bootstrap (αν απαιτείται). +* Κάθε αρχείο JavaScript πρέπει να διατηρεί **ένα μοναδικό component**. Το αρχείο πρέπει να ονομαστεί με το όνομα του component. +* Χρησιμοποιείστε ένα template απ το AngularJS, όπως τα [Yeoman](http://yeoman.io), [ng-boilerplate](http://ngbp.github.io/ngbp/#/home). -Conventions about component naming can be found in each component section. +Συμβάσεις σχετικά με την ονοματολογία των components, μπορείτε να βρείτε σε καθεμιά από τις ενότητες των components. ## Markup -[TLDR;](http://developer.yahoo.com/blogs/ydn/high-performance-sites-rule-6-move-scripts-bottom-7200.html) Put the scripts at the bottom. +[TLDR;](http://developer.yahoo.com/blogs/ydn/high-performance-sites-rule-6-move-scripts-bottom-7200.html) Βάλτε τα scripts στο τέλος. ```html From 3547798847fe03f631f29bd5104fad371a24d447 Mon Sep 17 00:00:00 2001 From: Thodoris Bais Date: Sun, 13 Aug 2017 04:32:20 +0200 Subject: [PATCH 4/4] Update README-gr-gr.md --- README-gr-gr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-gr-gr.md b/README-gr-gr.md index 45520a3..9ab5be1 100644 --- a/README-gr-gr.md +++ b/README-gr-gr.md @@ -234,7 +234,7 @@ services ``` -Keep things simple and put AngularJS specific directives after standard attributes. This will make it easier to skim your code and will make it easier to maintain because your attributes are consistently grouped and positioned. +Κρατήστε τα πράγματα απλά και βάλτε τα συγκεκριμένα directives του AngularJS μετά από κοινές ιδιότητες. Αυτό θα διευκολύνει να ελαφρύνετε τον κώδικά σας, όπως επίσης και να τον συντηρήσετε, μιας και οι ιδιότητές σας είναι ομαδοποιημένες και τοποθετημένες με συνέπεια. ```html