Commit | Line | Data |
---|---|---|
66aa0f5e TO |
1 | # org.civicrm.afform |
2 | ||
3 | ![Screenshot](/images/screenshot.png) | |
4 | ||
83291832 TO |
5 | The Affable Administrative Angular Form Framework (`afform`) is a system for administering AngularJS-based forms |
6 | in CiviCRM which: | |
7 | ||
8 | 1. Allows developers to declaratively define a canonical, baseline form. | |
3dc7610d TO |
9 | 2. Allows administrators (or administrative tools) to use the CRUD API to customize the forms. |
10 | 3. Allows developers to embed these forms in other AngularJS apps. | |
11 | 4. (WIP; pending upstream support) Allow developers to apply [change sets](https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/). | |
66aa0f5e TO |
12 | |
13 | The 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 | ||
22 | This extension has not yet been published for installation via the web UI. | |
23 | ||
24 | ## Installation (CLI, Zip) | |
25 | ||
26 | Sysadmins and developers may download the `.zip` file for this extension and | |
27 | install it with the command-line tool [cv](https://github.com/civicrm/cv). | |
28 | ||
29 | ```bash | |
30 | cd <extension-dir> | |
31 | cv dl org.civicrm.afform@https://github.com/FIXME/org.civicrm.afform/archive/master.zip | |
32 | ``` | |
33 | ||
34 | ## Installation (CLI, Git) | |
35 | ||
36 | Sysadmins and developers may clone the [Git](https://en.wikipedia.org/wiki/Git) repo for this extension and | |
37 | install it with the command-line tool [cv](https://github.com/civicrm/cv). | |
38 | ||
39 | ```bash | |
40 | git clone https://github.com/FIXME/org.civicrm.afform.git | |
41 | cv en afform | |
42 | ``` | |
43 | ||
76a5831d | 44 | ## Development: Quick Start |
66aa0f5e | 45 | |
3dc7610d TO |
46 | As an extension author, you can define a form along with its default, |
47 | canonical content. Simply create a folder named `afform/<MY-FORM>`. In | |
1e03a3c1 TO |
48 | this 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 | ||
58 | A 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 | ||
67 | Now 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 | ||
76 | You can open the given URL in a web-browser. | |
77 | ||
76a5831d | 78 | ## Development: Form CRUD API |
1e03a3c1 | 79 | |
76a5831d | 80 | Now that we've defined a baseline form, it's possible for administrators and |
3dc7610d | 81 | GUI 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 | ||
102 | Additionally, 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 |
117 | A 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 | ||
128 | In AngularJS, every component has its own *scope* -- which defines a list of variables you can access. | |
129 | ||
130 | By 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 | 138 | In the quick-start example, we registered a new route (`"server_route": "civicrm/pretty-page"`) -- this created a |
3dc7610d TO |
139 | simple, standalone page with the sole purpose of displaying the `foobar` form. But that had very limited information. |
140 | What if we want control the environment a bit more? | |
bb56ac78 | 141 | |
3dc7610d TO |
142 | There's no obligation to use the simple, standalone version of `foobar`. Think of `foobar` as a *re-usable sub-form* |
143 | or as a *directive*. If you've created an AngluarJS application, then you can embed `foobar` with two small steps: | |
bb56ac78 | 144 | |
76a5831d TO |
145 | 1. In your application, declare a dependency on module `afformFoobar`. This is usually done in `ang/MYMODULE.ang.php` |
146 | and/or `ang/MYMODULE.js`. | |
147 | 2. In your HTML template, use the directive `<div afform-foobar=""></div>`. | |
148 | ||
149 | This technique is particularly useful if you want to provide extra data for the form author to use. For example, your | |
150 | application might pass in the current phase of the moon: | |
151 | ||
152 | ```html | |
153 | <div afform-foobar="{phaseOfMoon: 'waxing'}"></div> | |
154 | ``` | |
155 | ||
156 | Now, in `afform/foobar/layout.html`, you can use the `phaseOfMoon`: | |
157 | ||
158 | ```html | |
159 | Hello, {{routeParams.name}}. The moon is currently {{options.phaseOfMoon}}. | |
160 | ``` | |
161 | ||
162 | ||
163 | ```html | |
164 | Hello, {{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`. |