Now works with npm.
Add structure to your AngularJS controllers
Angular's controllers are super-simple which is fantastic for getting started (they're just functions). Because they are just functions, there's lots of different ways to write Angular controllers. This is powerful but can also lead to a lack of structure, especially when many people (with many different coding styles) are working on the same codebase.
It can be helpful to have something a little more structured and prescriptive. Enter Angular Classy!
Injecting Dependencies
Angular veterans will know that if you want your Angular code to work with minifiers then you have to annotate your dependencies (i.e. list your dependencies twice), like so (without Classy):
app.controller('AppCtrl',
['$scope', '$location', '$http',
function($scope, $location, $http) {
// ...
}]);
If you want to add/remove a dependancy then you need to remember to do it in two places.
In Classy you don't need to do that, it works with minifiers and your code remains DRY. Here's what it looks like with Classy:
app.classy.controller({
name: 'AppCtrl',
inject: ['$scope', '$location', '$http'],
// ...
});
Accessing $scope
and dependencies
Dependencies are available using this.DependencyName
.
To access the $scope
You can simply write this.$.foo = 'bar';
instead of this.$scope.foo = 'bar';
. Although you can use still use this.$scope
if you prefer.
Want to use controllerAs
instead of $scope
? ▾
Initialisation
Classy provides a canonical place to init things. It's an init
method!
At a glance you can quickly see what your controller does when it initialises, no more searching through your controller. Simples!
Data Initialisation
There is also a data
property available for defining initial data properties. This will enable you to remove a lot of boilerplate assignment out of your init
method.
The data
object allows you to use the full power of Angular expressions when defining data properties.
data: {
todos: 'todoStorage.get()',
editedTodo: null
}
What's the alternative syntax? ▾
Watching Properties
Instead of polluting your init
method with lots of calls to $scope.$watch
, you can put them in a watch object instead:
watch: {
'location.path()': function(newValue, oldValue) {
// ...
},
'{object}todos': function (newValue, oldValue) {
// ...
}
}
Notice the {object}
keyword in the second listener above. This allows you to easily specify the type of watcher to use. This is much more explicit than Angular's approach. Here is a table of the available keywords:
Keyword | Equivalent $watch Type |
---|---|
{collection} or {shallow}
|
$watchCollection(..)
|
{object} or {deep}
|
$watch(.., objectEquality = true)
|
Methods
Most of the time when you add a method to a controller, you want it available on the $scope
. This is so that you can easily call it in your html using directives like ng-click
. Here is how methods look with Classy:
methods: {
editTodo: function(todo) {
//...
},
_clearCompletedTodos: function() {
//...
}
}
If you don't want the function to be on the $scope
then just prefix it with an underscore character (_
).
Method Expressions
You can now define methods using angular expressions. Whenever the method is called it will evaluate the expression and return the expression's result. Often, an expression will be much more concise and readable than a full method definition.
methods: {
getLast5CompletedTodos: 'todos | filter:{completed: true} | orderBy:"timestamp" | limitTo:5'
}
Plugins
Angular Classy now supports plugins so you can extend Classy with useful features that allow you to write computed properties and even extend controller classes.
If you want to write your own plugins then head on over to the classy-plugins repo for more information. This will be expanded with more detail over time, if you have a question then raise an issue.
You can see a list of the current Classy plugins on libraries.io.
Only 2KB (gzipped and minified)
it's super tiny so you don't have to worry about it adding weight to your application.
FAQs
Click the questions below to expand the answers.
How do I use Classy Controllers in a directive? ▾
How do I reference a Classy controller in a route? ▾
How do I use Classy with the `TodoCtrl as todo` syntax? ▾
Can I chain Classy Controllers? ▾
What's performance like? ▾
What's on the roadmap for future versions? ▾
Sorry, but I don't like the look of Classy controllers! ▾
How do I ask a question that isn't answered here? ▾
Add ‘classy’ to your app modules
var app = angular.module('app', ['classy']);
Register your controller and inject your dependencies.
Injecting dependencies with Classy plays nice with minifiers, you don’t need to annotate
your dependencies (i.e. list dependencies twice) and your code remains DRY.
By the way you can use the shortcut app.cC
instead of app.classy.controller
if you prefer.
app.classy.controller({
name: 'TodoController',
inject: ['$scope', 'todoStorage'],
New in 1.0! The data object is a simple structure that allows you to easily assign properties.
You can use a string representing an angular expression,
or you can directly assign any other object/primitive.
Classy automatically makes items in the data object available class-wide (and on the $scope
).
This feature helps to move boilerplate assignments out of the init
method.
data: {
items: 'todoStorage.get()'
},
An init method for your initialization code!
You can access your dependencies using the class-wide this
symbol.
The $scope
is available using this.$
(or you can use this.$scope
if you prefer).
init: function() {
this._resetEntryField();
},
Instead of polluting your init method with calls to $scope.$watch
,
you can put your watchers in the watch object instead.
If you want to watch an object or collection just use the {object}
or {collection}
keyword.
watch: {
'{object}items': '_onTodoChange'
},
New in 1.0! Controller methods are defined inside of the methods
object.
Classy automatically makes methods available class-wide (through this.methodName
) and also on the $scope
so you can easily access it using directives like ng-click.
Prefix the method name with an underscore and Classy wont add it to the $scope
.
You can also define methods using angular expressions (see _getRemainingCount()
).
Whenever the expression method is called it will evaluate the expression and return the expression’s result.
methods: {
_getRemaining: 'items | filter:{ complete: false }',
_onTodoChange: function() {
this.$.remainingCount = this._getRemaining().length; //!
this.todoStorage.put(this.items); //!
},
addTodo: function () {
this.$.items.push({text: this.$.newTodo, complete: false}); //!
this._resetEntryField(); //!
},
_resetTodoEntry: function() {
this.$.newTodo = ''; //!
}
}
}); //!
Installation
-
Or, install with bower:
bower install angular-classy
-
Reference Classy after the reference to Angular
If you're using npm, then you can do<script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-classy/angular-classy.min.js"></script>
-
Add Classy to your application module
var app = angular.module('app', ['classy']);
- That's it, you can create a
classy.controller
like so:app.classy.controller({ name: 'MyCtrl', inject: ['$scope'], init: function() { } });
Using with npm
- Install with npm:
npm install angular-classy
-
Add Classy to your application module:
var angular = require('angular'); var classy = require('angular-classy'); var app = angular.module('app', [classy]);
More Info
- Version: 1.2.4 (Releases/Changelogs)
- Github Repo
- Star
- Test status:
- License: MIT
- Author: Dave Jeffery
- Find Angular Classy useful? Share it on twitter!
- Looking for 0.4.x instead?