README.md
[civicrm-core.git] / ext / afform / README.md
CommitLineData
66aa0f5e
TO
1# org.civicrm.afform
2
3![Screenshot](/images/screenshot.png)
4
83291832
TO
5The Affable Administrative Angular Form Framework (`afform`) is a system for administering AngularJS-based forms
6in CiviCRM which:
7
81. Allows developers to declaratively define a canonical, baseline form.
3dc7610d
TO
92. Allows administrators (or administrative tools) to use the CRUD API to customize the forms.
103. Allows developers to embed these forms in other AngularJS apps.
114. (WIP; pending upstream support) Allow developers to apply [change sets](https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/).
66aa0f5e
TO
12
13The extension is licensed under [AGPL-3.0](LICENSE.txt).
14
15## Requirements
16
17* PHP v5.4+
83291832 18* CiviCRM v5.3+
66aa0f5e
TO
19
20## Installation (Web UI)
21
22This extension has not yet been published for installation via the web UI.
23
24## Installation (CLI, Zip)
25
26Sysadmins and developers may download the `.zip` file for this extension and
27install it with the command-line tool [cv](https://github.com/civicrm/cv).
28
29```bash
30cd <extension-dir>
31cv dl org.civicrm.afform@https://github.com/FIXME/org.civicrm.afform/archive/master.zip
32```
33
34## Installation (CLI, Git)
35
36Sysadmins and developers may clone the [Git](https://en.wikipedia.org/wiki/Git) repo for this extension and
37install it with the command-line tool [cv](https://github.com/civicrm/cv).
38
39```bash
40git clone https://github.com/FIXME/org.civicrm.afform.git
41cv en afform
42```
43
76a5831d 44## Development: Quick Start
66aa0f5e 45
3dc7610d
TO
46As an extension author, you can define a form along with its default,
47canonical content. Simply create a folder named `afform/<MY-FORM>`. In
1e03a3c1
TO
48this example, we create a form named `foobar`:
49
50```
51$ cd /path/to/my/own/extension
52$ mkdir -p afform/foobar
76a5831d
TO
53$ echo '{"server_route": "civicrm/pretty-page"}' > afform/foobar/meta.json
54$ echo '<div>Hello {{routeParams.name}}</div>' > afform/foobar/layout.html
1e03a3c1 55$ cv flush
76a5831d
TO
56```
57
58A few things to note:
59
3dc7610d 60* We defined a route `civicrm/pretty-page`. This is defined in the same routing system used by CiviCRM forms.
76a5831d
TO
61* The file `layout.html` is an AngularJS HTML document. It has access to all the general templating features, such as variable substition
62 (`{{routeParams.name}}`) and the standard library of directives (`ng-if`, `ng-style`, `ng-repeat`, etc).
63* After creating a new form or file, we should flush the cache.
64* If you're going to actively edit/revise the content of the file, then you should navigate
65 to **Administer > System Settings > Debugging** and disable asset caching.
66
67Now that we've created a form, we'll want to determine its URL:
68
69```
70$ cv url civicrm/pretty-page
71"http://dmaster.localhost/civicrm/pretty-page"
72$ cv url civicrm/pretty-page/#/?name=world
73"http://dmaster.localhost/civicrm/pretty-page/#/?name=world"
1e03a3c1
TO
74```
75
76You can open the given URL in a web-browser.
77
76a5831d 78## Development: Form CRUD API
1e03a3c1 79
76a5831d 80Now that we've defined a baseline form, it's possible for administrators and
3dc7610d 81GUI applications to inspect the form using the API:
1e03a3c1
TO
82
83```
84$ cv api afform.getsingle name=foobar
85{
86 "name": "foobar",
87 "requires": [
3dc7610d 88 "afformCore"
1e03a3c1
TO
89 ],
90 "title": "",
91 "description": "",
92 "layout": {
93 "#tag": "div",
94 "#children": [
76a5831d 95 "Hello {{routeParams.name}}"
1e03a3c1
TO
96 ]
97 },
98 "id": "foobar"
99}
3dc7610d
TO
100```
101
102Additionally, you can also update the forms:
103
104```
1e03a3c1
TO
105$ cv api afform.create name=foobar title="The Foo Bar Screen"
106{
107 "is_error": 0,
108 "version": 3,
109 "count": 2,
110 "values": {
111 "name": "foobar",
112 "title": "The Foo Bar Screen"
113 }
114}
115```
116
3dc7610d
TO
117A few important things to note about this:
118
119* The changes are only applied on this site.
120* Once you make a change with the CRUD API, there will be two copies of the form:
121 * `[myextension]/afform/foobar/` is the default, canonical version.
122 * `[civicrm.files]/afform/foobar/` is the locally customized version.
123* The `layout` field is stored as an Angular-style HTML document (`layout.html`), so you can edit it on disk like
124 normal Angular code. However, when CRUD'ing the `layout` through the API, it is presented in JSON-style.
125
76a5831d
TO
126## Development: Scope variables and functions
127
128In AngularJS, every component has its own *scope* -- which defines a list of variables you can access.
129
130By default, `afform` provides a few variables in the scope of every form:
131
132* `routeParams`: This is a reference to the [$routeParams](https://docs.angularjs.org/api/ngRoute/service/$routeParams)
133 service. In the example, we used `routeParams` to get a reference to a `name` from the URL.
134* `ts`: This is a utility function which translates strings, as in `{{ts('Hello world')}}`.
1e03a3c1 135
76a5831d 136## Development: Every form is an AngularJS directive
66aa0f5e 137
76a5831d 138In the quick-start example, we registered a new route (`"server_route": "civicrm/pretty-page"`) -- this created a
3dc7610d
TO
139simple, standalone page with the sole purpose of displaying the `foobar` form. But that had very limited information.
140What if we want control the environment a bit more?
bb56ac78 141
3dc7610d
TO
142There's no obligation to use the simple, standalone version of `foobar`. Think of `foobar` as a *re-usable sub-form*
143or as a *directive*. If you've created an AngluarJS application, then you can embed `foobar` with two small steps:
bb56ac78 144
76a5831d
TO
1451. In your application, declare a dependency on module `afformFoobar`. This is usually done in `ang/MYMODULE.ang.php`
146 and/or `ang/MYMODULE.js`.
1472. In your HTML template, use the directive `<div afform-foobar=""></div>`.
148
149This technique is particularly useful if you want to provide extra data for the form author to use. For example, your
150application might pass in the current phase of the moon:
151
152```html
153<div afform-foobar="{phaseOfMoon: 'waxing'}"></div>
154```
155
156Now, in `afform/foobar/layout.html`, you can use the `phaseOfMoon`:
157
158```html
159Hello, {{routeParams.name}}. The moon is currently {{options.phaseOfMoon}}.
160```
161
162
163```html
164Hello, {{routeParams.name ? routeParams.name : 'anonymous'}}. The moon is currently {{options.phaseOfMoon ? options.phaseOfMoon : 'on hiatus'}}.
165```
bb56ac78 166
66aa0f5e
TO
167## Known Issues
168
83291832
TO
169* The code is currently written as a proof-of-concept. There are several `FIXME`/`TODO` declarations in the code
170 for checking pre-conditions, reporting errors, handling edge-cases, etc.
171* Although afforms are can be used in AngularJS, they don't fully support tooling like `cv ang:html:list`
172 and `hook_civicrm_alterAngular`. We'll need a core patch to allow that.
76a5831d 173* We generally need to provide more services for managing/accessing data (e.g. `crm-api3`).
3dc7610d
TO
174* Need to implement the `Afform.revert` API to undo local cusotmizations.
175* To allow full support for change-sets, we'll need to patch `civicrm-core`.