Coder Social home page Coder Social logo

johnpapa / angular-styleguide Goto Github PK

View Code? Open in Web Editor NEW
23.9K 23.9K 4.2K 4.04 MB

Angular Style Guide: A starting point for Angular development teams to provide consistency through good practices.

Home Page: http://johnpapa.net

License: MIT License

angular-styleguide's Introduction

Hello ๐Ÿ‘‹

Twitter

angular-styleguide's People

Contributors

7upcat avatar albertoimpl avatar angelochiello avatar bensinther avatar binggg avatar bogatinov avatar ccschmitz avatar djyde avatar ericlemerdy avatar ewertoncodes avatar gaboesquivel avatar ingilniero avatar irvandoval avatar jedgell avatar jlcarvalho avatar jodytate avatar johnpapa avatar lucious7 avatar mazhekin avatar michaelbazos avatar noritamago avatar prayagverma avatar richardlitt avatar robertd avatar tomoyukikashiro avatar vinicius-sabadim avatar vinicius33 avatar wardbell avatar zachlysobey avatar zirho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-styleguide's Issues

Filters?

Should there be a section on filters?

Vendors

I would like to propose adding that you should make all libraries injectable for testability and consistency. For example, if you use momentjs, don't rely on the global exposure of the moment variable, instead, register it as a constant and inject it anywhere it's used. (Especially since moment in particular will be depricating the global variable in an upcoming release).

[Q] The mechanics of the Rule of 1

I'm not questioning the "Rule of 1", as you aptly put it. Rather, I've always tried to use the approach you suggest in my angular projects and struggled with it.. so, here's the question:

As you recommend, separating over multiple files:

// app.module.js
angular
    .module('app', ['ngRoute']);

// someController.js
angular
    .module('app')
    .controller('SomeController' , SomeController);
function SomeController() { }

// someFactory.js
angular
    .module('app')
    .factory('someFactory' , someFactory);

function someFactory() { }

But, doesn't this make all the parts less transportable/reusable?
The name of the app module ("app", in this case) now appears in all of the files, and if I wanted to reuse some of these components in a different project (where, to give in to our wildest side, we decided NOT to name the app module "app") I'd have to go on a hunt...

Am I silly in thinking of re-using Controllers in a different app?
Or should we look for a better organization?
For instance.. assuming we load the files in the right order (someController.js, someFactory.js before app.module.js), could we push the registrations into the app module file?
Should we?

// app.module.js
angular
    .module('app', ['ngRoute'])
.controller('SomeController', SomeController)
.factory('SomeFactory', SomeFactory);

// someController.js
function SomeController() { }

// someFactory.js
function someFactory() { }

[Question] Thoughts on multiple apps on same page

Not sure if this is something that needs to be added into the style guide or not, or whether this is just a general question, so apologises if this is the latter.

What are your thoughts on doing this:

http://stackoverflow.com/questions/24867578/multiple-apps-and-controllers-in-the-same-file/24867989#24867989

The reason that this has come up for us is that we are using Angular within SharePoint WebParts. This is working really well for us, until we need to add two webparts to the same page. Since angular will only bootstrap the first app that it finds, we have had to workaround the initial bootstrap and do this manually. While this works, it has a slight "smell" to it, and wondered what your thoughts are on this.

If it is frowned upon, do you have any suggestions for a better approach?

Using controllerAs in isolate scope directive

I want to bind scope max in vm. Here is sample code.

var directive = {
    restrict: 'EA',
    templateUrl: 'example.html',
    scope: {
        max: '='
    },
    controller : function($scope){
        var vm = this;
        vm.max = $scope.max; //is it true ? I want to show max value in example.html
    },
    controllerAs: 'vm'
}

Why IIFE

Hi,
why do we need IIFE if each file only contains one function ?

(function () {
    angular
        .module('app')
        .factory('logger', logger);

    function logger () { }
})();

Isn't this enough ?

/* Global var anyway*/
angular
    .module('app')
    .factory('logger', logger);

/* The rest of the code is in this function */
function logger () { }

Best way to handle a global actions bar?

Each view is a form. And the save and other action buttons are on top and is same everywhere. What will be the best approach for this?
A global directive for the action buttons and passing a method param to the directive?

Thanks in advance

How to layout vm values that need calculations?

For example see this gist here: https://gist.github.com/Siyfion/4783b72942f89ef2a805

The view model variable labelCountOptions and stockLabels both need to be calculated. Somehow doing them inline in the definition list seems messy and makes the controllers vm property list harder to skim-read. However, doing them where I've done them now doesn't seem quite right either...

The only other option I can see would be to create functions to initialize them, ie.

    vm.cancel = cancel;
    vm.filterInfo = {
      text: '',
      labelCount: ''
    };
    vm.labelCountOptions = calculateCountOptions();  // For example
    vm.user = AuthenticationService.getUser();
    vm.userLabels = labels;
    vm.selectLabel = selectLabel;
    vm.stockLabels = [];

    //////////////////////

    function calculateCountOptions () {
      return _.chain(vm.userLabels)
        .uniq('labelsPerSheet')
        .map('labelsPerSheet')
        .sort(function(a, b) {
          return a - b;
        })
        .value();
    }

Missing Commas in Modules

I noticed a few missing Commas in the Modules Section. Thank you for creating this awesome guide.

/* avoid */
var app = angular.module('app', [
    'ngAnimate',
    'ngRoute',
    'app.shared', // Add comma here
    'app.dashboard'
]);
/* recommended */
angular
    .module('app', [
    'ngAnimate',
    'ngRoute',
    'app.shared', // Add comma here
    'app.dashboard'
]);

Best practice for injecting providers?

Hi,

My excuses if I missed it, but how do you inject for exemple $http into a service/factory definition?

edit: to expand, should it be done like this?

// service

angular
    .module('app')
    .service('logger',[ '$http', '$sce', logger]);

function logger ($http, $sce) {
  this.logError = function (msg) {
    /* */
  };
}

Bindable members up top issue

As per the example:

  /* recommended */
  function Sessions() {
    var vm = this;

    vm.gotoSession = gotoSession;
    vm.refresh = refresh;
    vm.search = search;
    vm.sessions = [];
    vm.title = 'Sessions';

    ////////////

    function gotoSession() {
      /* */
    }

    function refresh() {
      /* */
    }

    function search() {
      /* */
    }
  }

You will get jshint errors like:

^ 'gotoSession' was used before it was defined.
^ 'refresh' was used before it was defined.
^ 'search' was used before it was defined.

Factory vs Service

I know the subject has been beaten to death, and I might be thick.
I've read this http://stackoverflow.com/questions/13762228/confused-about-service-vs-factory/13763886#13763886 and this http://stackoverflow.com/a/15666049

I still don't understand in which situation you should use one instead of the other. Since both returning a singleton, why not just pick the one you prefer (either Factory or Service) and exclusively use that one?

Why did the angularjs team feel it was necessary to support both ways?

Add promises

Style guide tips for using promises, both wrapped in angular services and using $q

Routing

guidelines for creating routing structures

Prototyping providers

Rather than place all provider (e.g. service, controller, etc) code in the constructor method, it can be more readable, result in better generated API documentation (e.g. using jsdoc) and is generally more performant to use prototypes over closures.

Example of this is below.

This may seem picky, but as this is a guide on good practice I think this deserves consideration. :)

Controller:

// foo-controller.js

/**
 * @constructor
 * @ngInject
 * @param {angular.Window} $window
 */
var FooController = function($window)
{
   /**
    * @type {angular.Window}
    * @private
    */
    this.window_ = $window;

    /**
     * @type {String}
     */
    this.alertMessage = '';
};

/**
 * Contrived example of a controller method...
 */
FooController.prototype.alert = function()
{
    this.window_.alert(
        this.alertMessage
    );
};
// foo-module.js

// Method of loading FooController is omitted. Use RequireJS, Browserify, Google Closure, etc...

angular.module('foo', [])
    .controller('FooController', FooController);
<!-- 
    foo.html 

    Assume this has been loaded using `FooController as foo` syntax.
-->

<input type="text" data-ng-model="foo.alertMessage" />

<button type="button" data-ng-click="foo.alert()">
    Alert!
</button>

If you agree, then I'd be happy to put a PR in to update the existing docs, plus add in examples for anything that's missing (e.g. directives).

Performance

Include watchers, bindonce, templatecache, and a slew of other fun stuff

how to call $scope.$broadcast when use vm=this?

TypeError: vm.$broadcast is not a function

when publishing and subscribing events using $emit, $broadcast, or $on consider moving these uses to a factory and invoke from the controller.

is there an example?

DataService Ravioli

how did I forget to add a data service example!?!? using $http and a promise

Question: How to inject from resolve after refactoring to follow style guide

Thanks for the style guide. I really like it overall and have been busy refactoring.
I have run across an issue using ui-router resolve and the different $inject syntax.

here is my state definition (using ui-router). No change to this (except "as vm"):

{
state: 'sample',
config: {
templateUrl: 'app/sample/templates/sample.html',
controller: 'Sample as vm',
resolve: {
sampleService: 'sampleService',
sampleItem: function ($stateParams, sampleService) {
return sampleService.getItem($stateParams.id).$promise;
}
}
}
}

I refactored the controller from this:

var sampleController = sampleModule.controller('sampleController',
function ($location, $scope, $state, $stateParams, sampleService, sampleItem)
{
...
}

To this:

(function () {
'use strict';

angular
    .module('sampleModule')
    .controller('sampleController', sampleController);

sampleController.$inject = ['$location', '$scope', '$state', '$stateParams', 'sampleService'];

function sampleController($location, $scope, $state, $stateParams, sampleService, sampleItem) {
   .....
}

But sampleItem is always null now (even though I can see through the $state.$current that the sampleItem object has been resolved.

Is there a way to inject it as a parameter as it was done previously?
looks like something missing from here:
sampleController.$inject = ['$location', '$scope', '$state', '$stateParams', 'sampleService', ??????];

Modularity section

How do you generally split the code to modules to prevent code duplication?

I've made an Angular module that adds support for class extensibility (angular-class-extender), but I'd love to hear more suggestions!!

introduce IIFE from the very beginning

Your note about IIFE deserves to be introduced from the very beginning, IMHO. It could be the first bullet in the existing Modules section, or, why not, perhaps even introduce a first "Basics" section where general/common patterns like this could be included.

Using Javascript strict mode

I know this is more of a general Javascript best practice, but having 'use strict;' in the IIFE template in the guide can help people avoid a lot of headaches (especially if they weren't aware of strict mode yet).

I also do things of the form:

(function(global){
   'use strict';
 ...
})(this);

To temper my usage of the global namespace except when necessary.

Controller as 'vm'

Hi John,

I'm not seeing the benefits of declaring 'ExampleCtrl as vm'. What is the intention by prefixing all template bindings with the same prefix, although their origin differs from each other ?

What do you think about declaring it semantically useful like 'ExampleCtrl as example' ? This way I can quickly identify the controller in use for the current html template just by looking at it. (Useful for example when maintaining multiple views and their respective controllers in multiple tabs).

Service injection in the routeProvider

In this example from the doc, is the injection of movieService in the resolve minification safe?

// route-config.js
angular
  .module('app')
  .config(config);

function config ($routeProvider) {
  $routeProvider
    .when('/avengers', {
      templateUrl: 'avengers.html',
      controller: 'Avengers',
      controllerAs: 'vm',
      resolve: {
        moviesPrepService: function (movieService) {
            return movieService.getMovies();
        }
      }
    });
}

ngAnnotate - ngInject not required in example...

In the ngAnnotate example below, I thought I'd just point out that the /* @ngInject */ isn't actually required in this specific instance.

angular
  .module('app')
  .controller('Avengers', Avengers);

/* @ngInject */
function Avengers (storageService, avengerService) {
  var vm = this;
  vm.heroSearch = '';
  vm.storeHero = storeHero;

  function storeHero(){
    var hero = avengerService.find(vm.heroSearch);
    storageService.save(hero.name, hero);
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.