From 52eabe30bb897f7d79fa06e63a1266834a08aeae Mon Sep 17 00:00:00 2001 From: Tim Otten <totten@civicrm.org> Date: Mon, 5 Jun 2017 21:36:05 -0700 Subject: [PATCH] "AngularJS: Loader" - Various updates --- docs/framework/angular/loader.md | 120 +++++++++++++--------- docs/hooks/hook_civicrm_angularModules.md | 19 +++- 2 files changed, 88 insertions(+), 51 deletions(-) diff --git a/docs/framework/angular/loader.md b/docs/framework/angular/loader.md index 05bf3415..4041166b 100644 --- a/docs/framework/angular/loader.md +++ b/docs/framework/angular/loader.md @@ -1,7 +1,11 @@ # AngularJS: Loader -What happens when a user visits a CiviCR-Angular page, such as -`https://example.org/civicrm/a/#/mailing/new`? Broadly speaking, two steps: +What happens when a user visits a CiviCR-Angular page? For example, let's +consider this URL: + + * `https://example.org/civicrm/a/#/mailing/new` + +Broadly speaking, two things happen: 1. (Server-side) CiviCRM processes the request for `civicrm/a`. It displays a web-page with all your Angular modules. @@ -13,19 +17,64 @@ The client-side behavior is well-defined by Angular server-side in greater depth because that is unique to the CiviCRM-Angular integration. -## The default base page (`civicrm/a`) +## The library of AngularJS modules -CiviCRM includes a default base-page -- any module can add new routes on -this page. For example, the `crmMailing` module defines a route -`mailing/new`. You can view this at: +CiviCRM needs a list of available AngularJS modules. Technically, these +modules are defined via +[hook_civicrm_angularModules](/hooks/hook_civicrm_angularModules.md), e.g. - * `https://example.org/civicrm/a/#/mailing/new` +```php +/** + * Implements hook_civicrm_angularModules. + */ +function foobar_civicrm_angularModules(&$angularModules) { + $angularModules['myBigAngularModule'] = array( + 'ext' => 'org.example.foobar', + 'basePages' => array('civicrm/a'), + 'requires' => array('crmUi', 'crmUtils', 'ngRoute'), + 'js' => array('ang/myBigangularModule/*.js'), + 'css' => array('ang/myBigangularModule/*.css'), + 'partials' => array('ang/myBigangularModule'), + ); +} +``` + +!!! tip "Tip: Generating skeletal code with `civix`" + In practice, this skeletal code can be autogenerated usin `civix`. + For details, see [AngularJS: Quick Start](/framework/angular/quickstart.md). + +The list of available modules varies depending on your system configuration: +if you install more CiviCRM extensions, then you might have more Angular +modules. Use `cv` to inspect the list of available Angular modules: + +``` +$ cv ang:module:list +For a full list, try passing --user=[username]. ++-------------------+-------------+------------------------------------------------------------------------------------+ +| name | basePages | requires | ++-------------------+-------------+------------------------------------------------------------------------------------+ +| angularFileUpload | civicrm/a | | +| bw.paging | (as-needed) | | +| civicase | (as-needed) | crmUi, crmUtil, ngRoute, angularFileUpload, bw.paging, crmRouteBinder, crmResource | +| crmApp | civicrm/a | | +| crmAttachment | civicrm/a | angularFileUpload, crmResource | +| crmAutosave | civicrm/a | crmUtil | +| crmCaseType | civicrm/a | ngRoute, ui.utils, crmUi, unsavedChanges, crmUtil, crmResource | +... +``` + +!!! tip "Tip: More options for `cv ang:module:list`" + * Use `--columns` to specify which columns to display. Ex: `cv ang:module:list --columns=name,ext,extDir` + * Use `--out` to specify an output format. Ex: `cv ang:module:list --out=json-pretty` + * Use `--user` to specify a login user using with. This may reveal permission-dependent modules. Ex: `cv ang:module:list --user=admin` -The default base-page is special because *all registered Angular modules -will be included by default*. You can expect the markup to look roughly -like this: +## The default base page (`civicrm/a`) + +CiviCRM includes a default base-page named `civicrm/a`. Any module can add new routes on +this page. The page might look like this: ```html +<!-- URL: https://example.org/civirm/a --> <html> <head> <script type="text/javascript" src="https://example.org/.../angular.js"></script> @@ -44,51 +93,26 @@ like this: </html> ``` -The PHP application instantiates `AngularLoader` +!!! note "In practice, the JS files may be aggregated and/or minimized." + +The markup is generated by a PHP class, `AngularLoader`, using logic like this: ```php $loader = new \Civi\Angular\AngularLoader(); -$loader->setPageName('civicrm/a'); $loader->setModules(array('crmApp')); +$loader->setPageName('civicrm/a'); $loader->load(); ``` The `load()` function determines the necessary JS/CSS/HTML/JSON resources -and loads them on the page. Roughly speaking, it outputs: - - - -More specifically, the `load()` function gets a list of all available -Angular modules (including their JS/CSS/HTTML files). Then it loads the -files for `crmApp` as well as any dependencies (like `crmUi`). - -The most important thing to understand is how it *gets the list of Angular -modules*. A few Angular modules are bundled with core (eg `crmUi` or -`crmUtil`), but most new Angular modules should be loaded via -[hook_civicrm_angularModules](/hooks/hook_civicrm_angularModules.md) - -For example, if you created an extension `org.example.foobar` with an -Angular module named `myBigAngularModule`, then the hook might look like: - -```php -/** - * Implements hook_civicrm_angularModules. - */ -function foobar_civicrm_angularModules(&$angularModules) { - $angularModules['myBigAngularModule'] = array( - 'ext' => 'org.example.foobar', - 'basePages' => array('civicrm/a'), - 'requires' => array('crmUi', 'crmUtils', 'ngRoute'), - 'js' => array('ang/myBigangularModule/*.js'), - 'css' => array('ang/myBigangularModule/*.css'), - 'partials' => array('ang/myBigangularModule'), - ); -} -``` - -!!! tip "`civix` code-generator" - In practice, you usually don't need to implement. The `civix` - code-generator creates a file named `ang/{mymodule}.ang.php` and - automatically loads as part of `hook_civicrm_angularModules`. +and loads them on the page. This will include: + * Any AngularJS modules explicitly listed in `setModules(...)`. (Ex: `crmApp`) + * Any AngularJS modules with matching `basePages`. (Ex: The value `civicrm/a` + is specified by both `setPageName(...)` and `myBigAngularModule` [above].) + * Any AngularJS modules transitively required by the above. +!!! note "What makes `civicrm/a` special?" + When declaring a module, the property `basePages` will default to + `array('civicrm/a')`. In other words, if you don't specify otherwise, + all modules are loaded on `civicrm/a`. diff --git a/docs/hooks/hook_civicrm_angularModules.md b/docs/hooks/hook_civicrm_angularModules.md index 21dd0901..0ce3c933 100644 --- a/docs/hooks/hook_civicrm_angularModules.md +++ b/docs/hooks/hook_civicrm_angularModules.md @@ -16,12 +16,23 @@ available in CiviCRM 4.6+. ## Parameters -- &$angularModules - an array containing a list of all Angular - modules. + * `&$angularModules` - an array containing a list of all Angular modules. Each item is keyed by the Angular module name. + +Each item `angularModules` may include these properties: + + * `ext` (`string`): The name of the CiviCRM extension which has the source-code. + * `js` (`array`): List of Javascript files. May use the wildcard (`*`). Relative to the extension. + * `css` (`array`): List of CSS files. May use the wildcard (`*`). Relative to the extension. + * `partials` (`array`): List of HTML folders. Relative to the extension. + * `requires` (`array`): List of AngularJS modules required by this module. Default: `array()`. (`v4.7.21+`) + * `basePages` (`array`): Uncondtionally load this module onto the given Angular pages. (`v4.7.21+`) + * If omitted, the default is `array('civicrm/a')`. This provides backward compatibility with behavior since `v4.6+`. + * For a utility that should only be loaded on-demand, use `array()`. + * For a utility that should be loaded in all pages use, `array('*')`. ## Returns -- null + * `null` ## Example @@ -32,6 +43,8 @@ available in CiviCRM 4.6+. ); $angularModules['myBigAngularModule'] = array( 'ext' => 'org.example.mymod', + 'requires' => array('ngRoute', 'crmUi'), + 'basePages' => array('civicrm/a'), 'js' => array('js/part1.js', 'js/part2.js'), 'css' => array('css/myAngularModule.css'), 'partials' => array('partials/myBigAngularModule'), -- GitLab