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