AngularJS: Quick Start¶
Let's create a new CiviCRM extension with an AngularJS page. It will present a small "About Me" screen.
Create a CiviCRM extension¶
First, we'll need a skeletal CiviCRM extension:
$ civix generate:module org.example.aboutme
Initalize module org.example.aboutme
Write org.example.aboutme/info.xml
Write org.example.aboutme/aboutme.php
Write org.example.aboutme/aboutme.civix.php
Write org.example.aboutme/LICENSE.txt
Create an Angular module¶
Of course, AngularJS also has its own module system -- any Angular routes,
directives, or services need to live within an Angular module
. Let's
create one.
$ cd org.example.aboutme
$ civix generate:angular-module
Initialize Angular module "aboutme"
Write ang/aboutme.ang.php
Write ang/aboutme.js
Write ang/aboutme.css
Tip: Angular module names
By default, civix
assumes that your Angular module name matches your
extension name. In this case, both are named aboutme
. However, this
is not required -- the option --am
can specify a different name. This
can be useful if you want to organize your code into multiple modules.
Note: ang/
folder
By convention, AngularJS source code is stored in the ang/
folder, and
each item is named after its module. The convention is discussed in
more detail in AngularJS: File Names
The first file, ang/aboutme.ang.php
, provides metadata for the PHP-based
file-loader, e.g.
return [
'requires' => ['ngRoute', 'crmUi', 'crmUtil'],
'js' => ['ang/aboutme.js', 'ang/aboutme/*.js', 'ang/aboutme/*/*.js'],
'css' => ['ang/aboutme.css'],
'partials' => ['ang/aboutme'],
'settings' => [],
];
The second file, ang/aboutme.js
, provides metadata for the JS-based
Angular runtime, e.g.
angular.module('aboutme', [
'ngRoute', 'crmUi', 'crmUtil'
]);
Tip: angular.module() and CRM.angRequires()
The list of dependencies is declared once in PHP and once in JS. To
remove this duplication, call CRM.angRequires(...)
, as in:
angular.module('aboutme', CRM.angRequires('aboutme'));
Add an Angular-based page¶
Now let's add a new Angular-based page. This page will require a route
with a controller
and an HTML template. The command
civix generate:angular-page
will create each of these:
$ civix generate:angular-page EditCtrl about/me
Initialize Angular page "AboutmeEditCtrl" (civicrm/a/#/about/me)
Write ang/aboutme/EditCtrl.js
Write ang/aboutme/EditCtrl.html
If you inspect the code, you'll find a basic AngularJS app which uses
$routeProvider
, angular.module(...).controller(...)
, and so on.
The generated code will display a small "About Me" screen with the current user's first-name and last-name.
Tip: Flush caches or enable debug mode
By default, CiviCRM aggregates AngularJS files and caches them. You can
flush this cache manually (cv flush
). However, it may be easier to
disable some of the aggregation/caching features by enabling debug
mode.
Open the page¶
Finally, we'd like to take a look at this page in the web-browser.
By default, CiviCRM combines all Angular modules into one page, civicrm/a
.
The URL of this page depends on your system configuration. Here are a few
examples:
# Example: Lookup the URL on Drupal 7
$ cv url 'civicrm/a/#/about/me'
"http://dmaster.l/civicrm/a/#/about/me"
# Example: Lookup the URL on WordPress
$ cv url 'civicrm/a/#/about/me'
"http://wpmaster.l/wp-admin/admin.php?page=CiviCRM&q=civicrm/a/#/about/me"
Tip: Open the browser from the command-line
If you're developing locally on a Linux/OSX workstation, pass the
option --open
to automatically open the page in a web browser.
Adding functionality¶
This section has useful methods for developing your form
Debugging¶
You can expose variables available in your angular page to the browser with
crm-ui-debug
. To expose myData
you would add the following.
<div crm-ui-debug="myData"></div>
The debug div is only visible if the user ALSO adds angularDebug=1
to the URL
Accessing url variables from the angular html¶
In order to access url variables in the html you need to do the following
- ensure the ngRoute directive is listed
in the ang.php file. This will happen by default if you create the form with
civix
. - Ensure
routeParams
is injected into the controller in the js file. E.g in this declaration the$scope
and$routeParams
are received.
angular.module('omnimail').controller('OmnimailomniGroupSync', function($scope, $routeParams) {
- Add the $routeParams
to the scope eg. in the html
$scope.routeParams = $routeParams;
- At this point you can access url variables in the html - eg. if 'id=1' is in the url
{{routeParams.id}} will display 1.
Note that if you create afforms routeParams
will be made available through the
afform infrastructure. For this reason it is good to standardise assigning
routeParams
as the variable name in the html.
When loading the form you can access route parameters in the js layer
by referring to $route.current.params.{my-paramter}
- eg.