Merge pull request #21620 from colemanw/purifier2
[civicrm-core.git] / ext / afform / docs / embed.md
CommitLineData
64423b13 1# Embedding Forms: Afform as reusable building-block
8a0ffdf9
TO
2
3In the [quick-start example](quickstart.md), we registered a new route (`"server_route": "civicrm/hello-world"`) -- this created a
4f4b6487 4simple, standalone page with the sole purpose of displaying the `helloWorld` form. What if we want to embed the form
9b5234b7 5somewhere else -- e.g. as a dialog inside an event-listing or membership directory? Afforms are actually *re-usable
8a0ffdf9
TO
6sub-forms*.
7
4f4b6487 8How does this work? Every `afform` is an *AngularJS directive*. For example, `hello-world` can be embedded with:
8a0ffdf9
TO
9
10```html
04417491 11<hello-world></hello-world>
8a0ffdf9
TO
12```
13
4f4b6487 14Moreover, you can pass options to `helloWorld`:
8a0ffdf9
TO
15
16```html
04417491 17<hello-world options="{phaseOfMoon: 'waxing'}"></hello-world>
8a0ffdf9
TO
18```
19
4f4b6487 20Now, in `ang/helloWorld.aff.html`, you can use `options.phaseOfMoon`:
8a0ffdf9
TO
21
22```html
23Hello, {{routeParams.name}}. The moon is currently {{options.phaseOfMoon}}.
24```
25
64423b13 26## Example: Contact record
8a0ffdf9
TO
27
28Is this useful? Let's suppose you're building a contact record page.
29
30First, we should make a few building-blocks:
31
3e29642c
TO
321. `ang/myContactName.aff.html` displays a sub-form for editing first name, lastname, prefix, suffix, etc.
332. `ang/myContactAddresses.aff.html` displays a sub-form for editing street addresses.
343. `ang/myContactEmails.aff.html` displays a sub-form for editing email addresses.
8a0ffdf9 35
3e29642c 36Next, we should create an overall `ang/myContact.aff.html` which uses these building-blocks:
8a0ffdf9
TO
37
38```html
39<div ng-form="contactForm">
40 <div crm-ui-accordion="{title: ts('Name')}">
04417491 41 <my-contact-name options="{cid: routeParams.cid}"></my-contact-name>
8a0ffdf9
TO
42 </div>
43 <div crm-ui-accordion="{title: ts('Street Addresses')}">
04417491 44 <my-contact-addresses options="{cid: routeParams.cid}"></my-contact-addresses>
8a0ffdf9
TO
45 </div>
46 <div crm-ui-accordion="{title: ts('Emails')}">
04417491 47 <my-contact-emails options="{cid: routeParams.cid}"></my-contact-emails>
8a0ffdf9
TO
48 </div>
49</div>
50```
51
3e29642c 52And we should create a `ang/myContact.aff.json` looking like
a8cb7414
TO
53
54```json
55{
04417491 56 "server_route": "civicrm/contact",
3e29642c 57 "requires" : ["myContactName", "myContactEmails", "myContactAddresses"]
a8cb7414 58}
6a7e9d50 59```
04417491 60> *Note: The parent afform will automatically require the `myContactName`, `myContactAddresses`, `myContactEmails` directives. You do not need to manually include them.*
8a0ffdf9 61
4f4b6487
TO
62We've created new files, so we'll need to flush the file-index
63
64```
65cv flush
66```
67
68and now we can open the page
69
70```
71cv open 'civicrm/contact?cid=100'
72```
73
3e29642c 74What does this buy us? It means that a downstream admin (using APIs/GUIs) can fork `ang/myContactName.aff.html` --
8a0ffdf9 75but all the other components can cleanly track the canonical release. This significantly reduces the costs and risks
36376a39 76of managing upgrades and changes.