Giter Club home page Giter Club logo

angularjs-styleguide's People

Contributors

adiman9 avatar alextsg avatar benbr-personal avatar chihab avatar ctaepper avatar davidnotes avatar etripier avatar jackpu avatar joaogarin avatar jodytate avatar josephlin55555 avatar josueggh avatar jvandemo avatar kurtpeters avatar lipis avatar lixey avatar maks3w avatar malikabed avatar nstanard avatar prayagverma avatar sebastibe avatar sryzycki avatar stephenpitchford avatar stryju avatar tadayosi avatar theredfish avatar timroes avatar toddmotto avatar vladimirvalov avatar vogloblinsky 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

angularjs-styleguide's Issues

Naming conventions

Why should we use component name for each file related to component? For instance, we have component main,

├── main
   ├── main.component.js
   ├── main.config.js
   ├── main.spec.js
   ├── index.js
   ├── main.html
   └── main.scss

files are located in main folder, it meens that these files related only to main component and I think it is not necessary add namespace name to each file

├── main
   ├── component.js
   ├── config.js
   ├── spec.js
   ├── index.js
   ├── main.html
   └── main.scss

component has child component

contacts
   ├── config.js
   ├── contacts.html
   ├── contacts.scss
   ├── controller.js
   ├── spec.js
   ├── edit
      ├── config.js
      ├── controller.js
      ├── edit.html
      ├── spec.js
      └── index.js

instead of

contacts
   ├── contacts.config.js
   ├── contacts.html
   ├── contacts.scss
   ├── contacts.controller.js
   ├── contacts.spec.js
   ├── edit
      ├── contacts.edit.config.js
      ├── contacts.edit.controller.js
      ├── edit.html
      ├── contacts.edit.spec.js
      └── index.js

Does it make sense?

Using ui-router 0.3.x (stable)

@toddmotto, for developers, such as myself, who aren't comfortable moving forward with an alpha release of ui-router, there is an alternative route-to-component approach. Starting with 0.3.0 a developer now has access to $resolve. While it requires being more verbose, it offers the following approach:

const todo = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .service('TodoService', TodoService)
  .config(($stateProvider, $urlRouterProvider) => {
    $stateProvider
      .state('todos', {
        url: '/todos',
        // full component html with binding attributes
        template: '<todo todo-data="$resolve.todoData"></todo>',
        resolve: {
          todoData: PeopleService => PeopleService.getAllPeople();
        }
      });
    $urlRouterProvider.otherwise('/');
  })
  .name;

First thoughts

Todd, this is awesome. I love to see these types of things being written in the Angular community. It's challenging, it's much needed, and it's refreshing. I have a few thoughts after reading through it and thinking about some of the things my team went through when building an ng 1.5 app using these principles and similar architecture.

Module exports

First, is there a reason not to just export the name from the module? It looks cleaner in the module setter, and has the same functionality. Instead of having to do:

import {Module} from './module';

angular.module([ Module.name ]) 

you could just do:

import { Module } from './module';

angular.module([Module])

My team think the latter snippet looks cleaner (for a couple reasons). There's not much benefit to doing it either way though, I suppose.

Naming convention

We mostly follow the naming pattern suggested here, but lately I've been wondering if it is necessary to name things like calendar.controller.js when Cmd+P in Atom, Sublime, etc. can find the controller in the calendar folder for you. Just a thought, but it would really cut down on the amount of typing you do for file names over time.

Binding readability

We found that having a utility file that exports a const for each of the binding types makes it easier to see what types of bindings are being used, and it's a little less "cypherish". Really helps with file readability. It's basically:

export const CALLBACK = '&';
export const ONE_WAY = '<';
export const STRING = '@';
  • Notice the omission?

DI

When writing apps with ES2015+, it's inevitable to need a build system. With that in mind, is it smarter to encourage the use of $inject or to strongly encourage ngAnnotate? Much less manual work, and much less error-prone with strict-di. I think it's better to let ngAnnotate do the heavy lifting, and it works with all the major build systems.

Class methods or pure functions?

From our experience, any pure functions that are not bound directly to our classes are easier to test in isolation. It's annoying to have to mock the controller and use ng-mocks to mock dependencies to test simple actions when you don't have to. Granted, we've tried to keep most of our functions are pure, and we've managed to rely very little on Angular services and dependency injection. It's been really nice and it's helped us a lot with writing tests and reusing code. Plus, mocha can run 600+ tests as quickly as you save a file. Karma can run 600+ tests about as fast as you can download angular 2 on a bad internet connection.

Lifecycle order

Another thing; one gotcha that got us over and over was that, somewhat inexplicably, $onChanges gets called before $onInit. I don't know where it's relevant to point that out, but it should probably be pointed out nonetheless.

Single-file components?

What's the benefit of defining the template inline, but not the controller? why not do:

const TodoComponent = {
  bindings: {
    whatever: '<',
  },
  controller: class TodoController {
    constructor(TodoService) {
      'ngInject';
      this.TodoService = TodoService;
    }
    $onInit() {
      this.newTodo = {
        title: '',
        selected: false
      };
      this.todos = [];

    this.TodoService.getTodos
      .then(response => this.todos = response);
    }
    addTodo(event.todo) {
      if (!event.todo) return;
      this.todos.unshift(event.todo);
      this.newTodo = {
        title: '',
        selected: false
      };
    }
  },
  template: `
    <div class="todo">
      <todo-form 
        todo="$ctrl.newTodo"
        on-add-todo="$ctrl.addTodo($event);">
      <todo-list 
        todos="$ctrl.todos"></todo-list>
    </div>
  `
};

We found that cutting file count whenever possible tends to help DX on a day-to-day basis. We've even tinkered with putting everything, even module definition, in one file. It tends to be kind of nice if you're keeping your components small.

Classes or arrow functions

That non-class directive pattern really seems a lot more natural to me. I know, I know, ng2. But still. Look how nice that looks, right? So clean, so little instantiating a class just to get the same functionality ¯\_(ツ)_/¯

File structure

Here's how we organize files. Not really suggesting this be the structure, just an another look at organization, may be helpful to someone:

├── client/
|  ├── app/
|  |  ├── redux/
|  |  |  └── modules/
|  |  |    └── events-signup/
|  |  |      ├── index.js
|  |  |      ├── selectors.js
|  |  |      └── state.js
|  |  └── scenes/
|  |  |  └── events-signup/
|  |  |    ├── index.js
|  |  |    ├── events-signup.controller.js
|  |  |    ├── events-signup.route.js
|  |  |    ├── events-signup.html
|  |  |    └── events-signup.scss
|  |  ├── index.js
|  |  └── reducers.js
|  └──global/
|     ├── core/
|     |  ├── core.config.js
|     |  ├── core.run.js
|     |  └── index.js
|     ├── components/
|     |  ├── nav/
|     |  |  ├── nav.js
|     |  |  ├── nav.scss
|     |  └── index.js
|     ├── scenes/
|     |  └── layout/
|     |     ├── index.js
|     |     ├── layout.route.js
|     |     ├── layout.scss
|     |     └── layout.controller.js
|     └── utils/
|        ├── bindings.js
|        ├── env.js
|        └── ng-utils.js
└── index.html

The reason global lives outside of app is the it contains a lot of utilities and boilerplate that isn't "app" specific, and could very easily be used by another application we want to quickly start building.

Also, we keep all state management (in our case, Redux) code outside of the components. If state is normalized correctly, it should be a 1:1 mapping to components, it should behave more like a database. We've just found this structure to help us think of our data independently of our components. We called all of our routes scenes I think just because of some React/Redux article I read somewhere or something, no benefit to scenes over routes

Require vs. bindings

Could we better explain the benefit of passing a binding instead of just requiring the parent? Devil's advocate: Why would i go through the long process of setting up all those bindings for one-way communication when I could just say require: '^^parentComponent' and accomplish the same thing, and cover all my bases in one line of code instead of 10+?

Using $event as the payload of & bindings

Using $event === smart. I love it, and wish I would've been doing that all along. It's much better to have that consistent API for outputs.

Use resolves to make smart components

Shoutout to Chris Thielen for this idea, but in a lot of cases, when you're routing straight to components, there's a good chance that most of the bindings you'd do in smart components can probably be done in resolves on a ui-router state. Just one more step that can be cut out.

NG2.0 vs. the world

Finally, I know there's been a lot of thought put into this style guide to help with transitioning to Angular 2. One of the thoughts that came to my head as I read this is: Do we, while catalyzing modern best practices in the community, want to encourage good Angular 2 practices, or good JavaScript practices. One example: there is HUGE benefit to factory functions. They're easy. They're perfect for the types of things we want a service to do. They're very useful. They're gone in ng2. RIP .factory().

I think one of the great things about the React community is that they truly strive to make people better JavaScript devs. To me, that's a useful thing. That transcends framework boundaries, and makes a lasting impact on all of us as developers. I really believe this guide, along with a lot of the things you write, are going to help foster more of that in the ng 1.x community. Thanks for doing what you do, and I'm looking forward to future discussions!

Named exports vs. defaults

This is a great guide!

I've been working with Angular 1.5 and ES6 for several months now, trying to find good ways to make it work and make it clean. I wasn't following any guides, and I got to almost the same practices as what you describe here. Therefore, I like it :)

I'm still reading this guide, but one thing that I do a little differently is exports and imports:

I use the same export pattern with the modules themselves, using export default angular.module('appStuff', ...).name, and then in the parent directory, I import it using import appStuffModule from ... to include it in the dependencies of the "container" module.

However, I export named components explicitly using their names, and not by default export. By this I mean components (or directives, if it can't be avoided), services, factories, providers, constants, functions and basically anything that's not a module that is exported by a variable.
An actual example from a project I'm working on (removed implementation and I'm also using TypeScript, but the idea is the same):

sysMonitor.ts

/**
 * @ngdoc controller
 * @name SysMonitorController
 */
class SysMonitorController {
  static $inject = ['$scope', 'dataProviderReportType', 'avrChartDataService', 'BIP_MultiDataProvider'];

  /*- Bindings -------------------------------------------------------------*/
  public timerange;

  /*- Template vars ($ctrl props) -------------------------------------*/
  public isLoading = false;
  public isOpen = true;
  // ...

  /*- Private props --------------------------------------------------------*/
  private chartConfig = <ILineChartConfig>{};
  private dataProvider: statsDataProvider;
  // ...

  /*- Public methods ----------------------------------------------------------*/
  /**
   * Constructor used for DIs and binding of methods
   */
  constructor(private $scope: ng.IScope,
              private dataProviderReportType,
              private avrChartDataService,
              private BIP_MultiDataProvider) {
    // binding callbacks from prototype to current instance
    this.onDataUpdated = this.onDataUpdated.bind(this);
  }

  public $onInit() {
    // After everything is initialized, prepare data providers and charts configuration
  }

  public $onChanges(changes) {
    // changes monitoring
  }

  public $onDestroy() {
    // remove callbacks from data providers
  }

  /*------------------------------------------------------------------------*/

  private onDataUpdated(data, error, notification) {
    // ...
  }

}

/**
 * @ngdoc component
 * @name avrSystemMonitor
 * @restrict E
 * @param timerange
 */
export const sysMonitorComponent: ng.IComponentOptions = {
  bindings: {
    timerange: '<'
  },
  controller: SysMonitorController,
  templateUrl: `...`
};

and then in a directly above it, I have components.ts

///<reference path="../../../../../../typings/index.d.ts"/>
import someServicesModule from '../services/someServices'; // <-- module
import { sysMonitorComponent } from "./sysMonitor/sysMonitor"; // <-- named component

/**
 * @ngdoc module
 * @name app.components
 */
export default angular
    .module('app.components', [
      someServicesModule
    ])
    .component('avrSystemMonitor', sysMonitorComponent)
    // ...
    .name;

And of course, one level above it, there is the main app.ts file which has, among others:

import componentsModule from './components/components'; // <-- I am still considering using 'index.js' (.ts) for the "glue" file in each directory.
// import other modules here
import { someConfigFunction } from './config';

/**
 * @ngdoc module
 * @name app
 */
angular.module('dosVisibility', [
    componentsModule,
    // other imported modules
  ])
  .config(['$compileProvider', function($compileProvider) {
    $compileProvider.debugInfoEnabled(false);
  }])
  .run(someConfigFunction);

The app file is the entry point (for webpack), so it doesn't really need an export. If it would have been a library, then the entry point would also have an export.

I find this pattern very useful. Additionally, exporting by name instead of defaults is pretty much the only way any IDE knows what you mean, even before you made the import.
For example, in both VSCode and JetBrains IDEs, you can use an object from another file, and it will automatically add the import. It will not do it for "default" export since the names mean nothing before these are imported. Just for this, I think it's worth to use named exports.

I wonder what are the thoughts of the community about it.

Services instead of factories

how would i apply this pattern to a ES2015 service?

function PersonService($http) {
  function Person() {
    this.foo = function () {

    };
  }
  Person.prototype.bar = function () {

  };
  return Person;
}
angular
  .module('app')
  .factory('PersonService', PersonService);

this is an example of your post at https://toddmotto.com/factory-versus-service

Why so specific in naming Services?

I've been living by this style guide for awhile now, and it's fantastic.

The Service naming is irritating, though. I'd suggest a more generic name for the Service object inside each service. Example:

function AnotherService () {
  var AnotherService = {};
  /* ... */
  return AnotherService;
}

could become...

function AnotherService () {
  var Service = {};
  /* ... */
  return Service;
}

There are two three reasons why:

  1. jsHint throws irritating "already defined" notices when the internal object is the same name.
  2. It makes it easier to rename services or repurpose snippets in other service.
  3. It's more consistent with the way that you're naming controller objects (always with "vm").

I'd love your thoughts on this. If there's a good reason, I'd like to know and avoid any issues.

Thank you!
Dustin

Controllers in Directives?

What you guys think in add something about this topic? I personality like to put all logic of a directive in controllers.. something like that:

.directive('myDirective', function(apiService){
    return {
        restrict: 'EA'
        controller: function($scope){
            $scope.fetch = function(){
                return apiService.getData();
            };
        },
        link: function(scope, element, attrs){
            var data = scope.fetch().then(function(){
                element.text(data);
            });
        }
    }
})

It's a good practice?

Thanks

Portuguese (Portugal pt-pt) version

Hello Todd,

I can submit a pt-pt translation if that is interesting. People from Brazil / Portugal and many countries from Africa would probably benefit from this. And since I saw a Spanish version was submitted, why not have it in some more languages?

=)

[Question] Typescript specifc remarks / info?

Hey Todd,
What would be your opinion about including some typescript related info into you guide?
If PRs are welcome, should those be included as a new chapter, or inline? I guess a new chapter would be less disturbing overall, but easier to miss...

Routing resolves

Hi,
about the Routing resolves solution you suggest, it looks very good but there is a problem when the controller is not in the same file as the app.js.

How do you suggest to solve it?

Spec file

Could you give an example of a spec file?

I'm wondering how do you plan your tests, since it might be a little awkward (at least to me) to mix service tests with controller tests on the same file?

I'm most likely missing something here, but I guess you could give some guidance.
Thanks :)

question about the way to unbind multiple listeners on $destroy

In event pub/sub section, why do we unbind listener within multiple $destroy event binding?

var rootListeners = {
  'customEvent1': $rootScope.$on('customEvent1'[, callback]),
  'customEvent2': $rootScope.$on('customEvent2'[, callback]),
  'customEvent3': $rootScope.$on('customEvent3'[, callback])
};
for (var unbind in rootListeners) {
  $scope.$on('$destroy', rootListeners[unbind]);
}

Can we do this instead? move for loop into the $destroy event handler

$scope.$on('$destroy', function() {
  for (var unbind in rootListeners) {
    rootListeners[unbind]();
  }
});

routed component

Hello todd,

thanks for this new version of your styleguide. You mention in routed component that we can use a component prop when declaring a state but I can't find any documentation in ui-router about it

    $stateProvider
      .state('todos', {
        url: '/todos',
        component: 'todo',
        resolve: {
          todoData: TodoService => TodoService.getTodos();
        }
      });
  })

I like the idea a lot can you have any infos on that ?

Generic standards

Is it worth considering splitting the document into generic JS and Angular specific standards with a view to, possibly, extending it to include, for example, specific Node practices (possibly rebranding the repo to js-styleguide??)?

For example, using JSDoc is a generic recommendation (and very poorly adopted) for JavaScript as a whole.

Also, running talks like this through a filter would also be worthwhile.

Just thinking out loud.

question/comment: routing resolves

Having a little difficulty following your section on Routing Resolves.

Note: I'm using Browserify, Restangular, and ui-router in my app.

You do the following in your example MainCtrl:
this.something = SomeService.something

MainCtrl appears to have a property of resolve (an obj; not a promise):

Main.resolve: {
  doSomething: function() { // How come `SomeService` doesn't need to be injected here??
    return SomeService.doSomething();
  }
}

I was thinking that you'd want to resolve doSomething before you instantiate the controller:

function config ($routeProvider) {
  $routeProvider
  .when('/', {
    templateUrl: 'views/main.html',
    controllerAs: 'main',
    controller: 'MainCtrl'
    resolve: MainCtrl.resolve.doSomething // instead of just resolve: MainCtrl.resolve
  });
}

I'm making the assumption that SomeService.doSomething() is a promise that's then'able...

SomeService.doSomething.then( function( somethings ) {
  // May want to map `somethings` to controller's $scope, but how??
});
Below is what I'm trying to accomplish by following the guide, but a bit lost on proper implementation...

Routing:

// league-config.js
...
$stateProvider
  .state('league.creation', {
        url: '/creation',
        controller: 'LeagueCreationController as leagueCreation',
        resolve: require('./league.creation-controller').resolve,
        views: {
          'main@': {
            templateUrl: './partials/league/league-creation.html'
          }
        }
      });

Controller:

// league.creation.controller.js
var LeagueCreationController =  function( Restangular ) {
    var self = this;
    var leagues = Restangular.all( 'leagues ');
    // Would be great if this could be resolved outside of the controller...
    leagues.getList().then(function( allLeagues ) {
      self.leagues = allLeagues;
    }
};

LeagueCreationController.resolve = {
  leagues: function( Restangular ) {
    return Restangular.all( 'leagues' ).getList();
  }
};

module.exports = LeagueCreationController;

Help is greatly appreciated. The guide is absolutely a joy to have. :)

Dependency injection for base controllers on Inheritance

The style guide presents this code:

function BaseCtrl () {
  this.doSomething = function () {

  };
}
BaseCtrl.prototype.someObject = {};
BaseCtrl.prototype.sharedSomething = function () {

};

AnotherCtrl.prototype = Object.create(BaseCtrl.prototype);

function AnotherCtrl () {
  this.anotherSomething = function () {

  };
}

My problem is with this line: AnotherCtrl.prototype = Object.create(BaseCtrl.prototype);

See in this case it works because BaseCtrl has no dependencies, but that's hardly the case in most scenarios, so I can't just use Object.create, what do we do then?

Angular wrapper references ( link fn params wrong)...

Hi Todd.

I think here is a typo, $document service should be injected as parameter of the directive function right?
instead of this:

// recommended
function dragUpload () {
  return {
    link: function ($scope, $element, $attrs, $document) {
      $document.addEventListener('click', function () {

      });
    }
  };
}

this:

// recommended
function dragUpload ($document) {
  return {
    link: function ($scope, $element, $attrs) {
      $document.addEventListener('click', function () {

      });
    }
  };
}

also I think, that it's a good practice, not to prefix positional link function arguments with dollar sign, because those are not injected services via DI.

And last one: It's more readable, imho, to extract controller/link/compile function outside of the directive definition object like this:

;(function () {
    angular.module('myApp', [])
        .directive('myDirective', myDirective);

    function myDirective( /* DI */ ) {

        return {
            restrict: 'EA',
            controller: Ctrl,
            controllerAs: 'ctrl',
            link: linkFn,
            template: '<div>My name is {{ ::ctrl.myName }}</div>'
        };

        function Ctrl($log) {
            // ...
            this.$log = $log;
            var vm = this;

            vm.myName = 'Martin';
        }

        Ctrl.prototype.sayHi = function () {
            this.$log(this.myName);
        }

        function linkFn(scope, element, attrs) {
            // ...
        }
    }
})();

What do you say?
thanks and btw you did a great job on writing this guide!

My Module declaration best practices

Great writeup!

I have found the following best advices.
Just my opinion, will be happy to know any possible flaws in my arguments.

  • Use only one angular.module("myModule",[...]) at the top of each file, with the file being called my-module.js. That way there is one-to-one correspondence between files and Modules and it is very easy to know where each Module is located.
  • As an extension of this rule, use myDirectory/myFile as Module name for my-directory/my-file.
  • Directory structure should possibly be flat to make search easier. Once a directory starts looking "too crowded", this becomes a reason to create a subdirectory.
  • Don't use angular.module("...") without [], use chaining instead! If you want to use it in another file - don't! Make your file a new Module and embed it instead!
  • Surprisingly the following simple pattern is not mentioned, which is the one I prefer:
angular
  .module('app', [])

  // anonymous function, no global variable
  .controller('MainCtrl', function () {

  })

  .service('SomeService', function () {

  })
;
// note how the semicolon is in its own line, 
// that makes it very easy to add/remove blocks

From my perspective, this way is superior to repeating the function name first as global variable, and then, again, inside module method. That repetition is not DRY. Also no global variable is created, so no IIFE is needed (but can still be used).

  • A good reason to use IIFE is to put use strict inside, which should not be in global scope.
  • Finally, angular modules are awesome because they can be loaded in any order! That means, I can simply concatenate my files with Gulp and so never need to worry about maintaining their paths :)

Minor grammatical/syntactical review

Hello,

This style guide is incredibly helpful and I've found it to be a great Angular resource. I'd like to contribute some minor grammatical and syntactical review; some of the language was slightly confusing, and I think small corrections would improve the guide's readability and clarity.

Example:
Before: "Directives and Filters are the only providers that we have the first letter as lowercase, this is due to strict naming conventions in Directives due to the way Angular translates camelCase to hyphenated, so dragUpload will become drag-upload when used on an element."

Proposed change: "Directives and Filters are the only providers that have the first letter as lowercase; this is due to strict naming conventions in Directives. Angular hyphenates camelCase, so dragUpload will become drag-upload when used on an element."

I won't be changing any of the examples or presented code, just grammatical gloss. Please let me know if this could be a valuable addition.

Can you explain why we should not bind resolve logic to the router?

Here it talks about putting our resolves in the controller, instead of in the router. This is interesting to me, because I thought that you wanted to keep your controllers as slim as possible (as a general rule, and in prep for Angular 2.0). Can you elaborate a little more about why you would want to put your resolve logic inside a controller?

Thanks! ^_^

$timeout & this

Given your controller with a $timeout:

function MainCtrl ($timeout) {
  this.clock = 'loading...';
  this.someObject = {};
  this.doSomething = function () {

  };

  var tick = function () {
    var today = new Date();
    // 'this.clock' isn't accessible here 
    $timeout(tick, 1000);
  };

  // Call it the first time to kick it off
  $timeout(tick, 0);
}

Should I be assigning a local variable like:

var _this = this;

// Then use (in the tick function):
_this.clock = today;

IIFE Scoping

In regards to:

(function () {

  // MainCtrl.js
  function MainCtrl () {

  }

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

  // SomeService.js
  function SomeService () {

  }

  angular
    .module('app')
    .service('SomeService', SomeService);

  // ...

})();

Would it not be better to pass the module in like:

(function (app) {

  // MainCtrl.js
  function MainCtrl () {

  }

  app.controller('MainCtrl', MainCtrl);

  // SomeService.js
  function SomeService () {

  }

  app.service('SomeService', SomeService);

  // ...

})(angular.module('app'));

Thoughts?

module file naming

First of all : great styleguide!

We are using a very similar approach for some time now. With one little difference in naming conventions: we call our module file index.js. This allows the module to be imported with import Todo from "./todo"; (instead of from "./todo/todo"). Also, everyone knows, index.* would be the start of a module directory. Any thoughts?

Add style guide for unit tests

Hi guys, this is a very helpful article. It'd be nice to have your thoughts on unit test structure and organisation for each type of Angular components (directives, services, filters, etc).

Controllers#Inheritance : what about BaseCtrl in the global namespace ???

The rule for inheritance seems to advocate to put ours base Controllers (the 'parent' controllers) in the global namespace ... since we cant use injector to get a reference to the base controller where we would want it ( in IIFE definition of another (child) Controller )...or am I missing something ?

Thanks a lot

About components and common module...

i thought about those modules while working on the other PR yesterday. you are not really explaining the purpose of those modules, other that one single place to inject component modules.

however, is this really best practice? lets take the common/footer component for example. you inject it via the common module into the root module, so the footer module is available throughout the whole app, i can use this component everywhere, for examples sake i use it now in my (view-) component called home which represents the initial view of my app. now, i want to test my home component in isolation. this component now no knowledge about the common/footer component, because you didn't explicitly inject the dependency into the module definition for home, but rely on the module being injected into the root module...

in our setup, we import and inject every single module that is required by the current module. at first, it seems like a bit of overhead, but this way, we always have all necessary dependencies available, when testing a module in isolation.

Controller resolve dont using then() to formatter response

Hi,

I have liked formatter response on Service before output.

from:

PlaylistsCtrl.resolve = {
    doSomething: function(PlaylistService) {
        return PlaylistService.getPlaylists();

to:

PlaylistsCtrl.resolve = {
    doSomething: function(PlaylistService) {
        var _list = PlaylistService.getPlaylists();
        _list = JSON.stringify(_list);

using algo then():

return PlaylistService.getPlaylists().then(function(response) {.......});

Who is?

Help me, please!

Edit

ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: playlist in playlists

HTML

<ion-list>
      <ion-item ng-repeat="vm in playlists track by $index | orderBy:'id'" href="#/app/playlists/{{ ::vm.id}}">
        {{ ::vm.title}}
      </ion-item>
    </ion-list>

controllers.js:

var ctrl = angular.module('starter.controllers', []);

...

function PlaylistsCtrl(PlaylistService) {
    this.something = PlaylistService.getPlaylists;
}
PlaylistsCtrl.resolve = {
    doSomething: function(PlaylistService) {
        return PlaylistService.getPlaylists();
    }
}
ctrl.controller('PlaylistsCtrl', function($scope, doSomething) {
    $scope.playlists = JSON.stringify(doSomething);
});

Controller.resolve versus IIFE

Hello,

I just wonder how you can use the Controller.resolve property when using IIFE (assuming the routing config and the controller are in separate files).
Using tools like Browserify solves this problem, but when you simply concat all your script files I don't see a way to use a property of the controller while configuring the router.
Any recommandation?

Services vs. Factories

"All Angular Services are singletons, using .service() or .factory() differs the way Objects are created."

It is correct that all Angular Services return singleton objects. The service gets the result of instantiating the constructor function passed. One adds properties to the singleton by referencing "this" in the constructor function.

Angular Factories, on the other hand, gets the returned value of the function, which may return singleton objects, primitive types, or functions. One can certainly "new" a Factory if the Factory function returns a function.

Missing import of AppComponent root component in the guide

It seems that the import of the root component AppComponent is missing in the styleguide (in this section in the app.js file)

Something like that I think :

import AppComponent from './app.component';

along with these:

import Common from './common/common';
import Components from './components/components';

or maybe I missed something ?

Overhaul this guide

This guide needs overhauling now Angular 1.5.x is out. Things to cover:

  • One-way dataflow (data down, events up)
  • Component method (and polyfill: https://github.com/toddmotto/angular-component)
  • Component architecture
  • Each block is a module (huge feature modules are obselete)
  • Stateful, stateless and routed components

Controller-as and "this"

Not sure if I'm missing something here, but you first recommend using Controller-as syntax, referencing "this" in the controller for model properties and methods. Then, further on, you recommend setting "this" to "vm" (for ViewModel). Should this just be one recommendation, using Controller-as syntax and assigning "this" to a variable in the context of the controller?

Thanks

What about file organization ?

I just discovered your styleguide, and it looks awesome ! I can't to use it.

But, I think a chapter about file organization would be nice.

I just saw this : https://github.com/andyjessop/angular-starter#file-structure

But I'm not sure this is the organization I want : in this example, if I have a user registration and a user profile stuff, this would be two different modules, or I should put many views, controllers, services... in the same folder... this would look messy...

Anyway, what's the best practice for file organisation ?

ng-bind vs curly brackets

Hi everybody!

I read this guide and try to follow advices contained here, but today I faced problem with curly brackets, because I had JS imports in <footer> element at bottom of page - I had to move it to <head> section and use ng-cloak on body (which isn't adviced... But works 😄 ). Then I found ngBind directive, which completely removes this problem. As I googled, it is also faster than {{}} but some people are complaining that it created unnecessary boxing with <span ng-bind="something"></span> and isn't as clear as curly brackets syntax (maybe it's only old habit?). I am curious of your opinion - maybe it's worth mentioning in @toddmotto's / @johnpapa's styleguides?

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.