Upfront: This document is working draft and far from being perfect. We will improve this over time as we do more work with AngularJS.
With using AngularJS we are trying to achieve different goals:
I recommend watching some videos and read a few resources about the benefits and best practices of AngularJS. It is important to understand how AngularJS works and especially to be aware of pitfalls and best practices.
It is very important to understand AngularJS Scopes.
<div ng-model="model.searchfield">instead of
view. For instance
Serviceis a Singleton and whenever you request a service the same instance will be returned
Providershave the advantage that they can be configured during the module configuration phase. A service and factory are both provider. Read more
.finally()won't work in IE8. Use
promise['finally']()instead. Read more
There are lots of discussions about the best file structure. In the past we divided a feature into multiple folders called
stylesheets, ... From now on we want to
organize files per feature which is recommended by the Angular Team and also works best in large projects.
Basically we create a folder for each feature within the plugin folder. Say we want to create a "site selector" than we create the following files: + CoreHome + angularjs + siteselector + siteselector.directive.js + siteselector.directive.less + siteselector.directive.html + siteselector.controller.js + siteselector.filter.js + siteselector-model.service.js + search.png + common + images + filters + corehomespecific.js
Sometimes you might have some reusable components within your plugin in which case you can but them into a
What's the adventage of this? Beside that is scales with the project you will notice immediately what a plugin does when opening a plugin folder whereas this is not the case if you see only
stylesheets folders. Another advantage is we could - in theory - extract a feature into a separate repository and share single widgets with other people.
A module always ends with
.module.js. A service or factory always ends with
.service.js, a controller with
.controller.js, a directive with
.directive.js and a filter with
.filter.js. Filenames are lowercase and words should be separated by a dash:
site-selector.directive.js. If there is a config for an app the file has to be named as
There is currently the
angularjs namespace within a plugin which is a bit annoying, we know. Long term we will remove this folder. medium term - once we have more Angular components - we will give this folder at least a better, more meaningful, name. With the existing assets structure of jQuery code it is hard to find the least annoying solution for this.
For a more detailed naming convention have a look at the Angular Naming Guide.
If a component, say a filter, can be reused in different plugins and is not plugin specific we but them into
Filenames are always lower case and words are separated by dashes. In general, we have one file per type. The type - eg filter, directive or service - does not have to appear in the filename in this case as it is already placed in the related folder.
Important: Our directives always start with
piwik- for instance
Some features in Matomo are already realized by using AngularJS.
They make use of different components
We are currently not using AngularJS Routing. The goal is to use it in long term to get rid of piwikBroadcast and many other classes.
We use Karma + Chai + [Mocha] (https://mochajs.org/) to write unit tests. Read more about it here: https://github.com/matomo-org/matomo/blob/master/tests/angularjs/README.md
Might be interesting link: Docular
AngularJS dependency injection allows plugins to overwrite or extend whatever whey want, for instance a directive. A plugin architecture comes therefore more or less out of the box.
For instance a plugin can "hook" on to a certain directive, extend/change controller behaviour etc. This video might give you some ideas: https://www.youtube.com/watch?v=rzMrBIVuxgM
More to come!