Commit | Line | Data |
---|---|---|
64423b13 | 1 | # Embedding Forms: Afform as reusable building-block |
8a0ffdf9 TO |
2 | |
3 | In the [quick-start example](quickstart.md), we registered a new route (`"server_route": "civicrm/hello-world"`) -- this created a | |
4 | simple, standalone page with the sole purpose of displaying the `helloworld` form. What if we want to embed the form | |
9b5234b7 | 5 | somewhere else -- e.g. as a dialog inside an event-listing or membership directory? Afforms are actually *re-usable |
8a0ffdf9 TO |
6 | sub-forms*. |
7 | ||
8 | How does this work? Every `afform` is an *AngularJS directive*. For example, `helloworld` can be embedded with: | |
9 | ||
10 | ```html | |
11 | <div afform-helloworld=""></div> | |
12 | ``` | |
13 | ||
14 | Moreover, you can pass options to `helloworld`: | |
15 | ||
16 | ```html | |
17 | <div afform-helloworld="{phaseOfMoon: 'waxing'}"></div> | |
18 | ``` | |
19 | ||
20 | Now, in `afform/helloworld/layout.html`, you can use `options.phaseOfMoon`: | |
21 | ||
22 | ```html | |
23 | Hello, {{routeParams.name}}. The moon is currently {{options.phaseOfMoon}}. | |
24 | ``` | |
25 | ||
64423b13 | 26 | ## Example: Contact record |
8a0ffdf9 TO |
27 | |
28 | Is this useful? Let's suppose you're building a contact record page. | |
29 | ||
30 | First, we should make a few building-blocks: | |
31 | ||
32 | 1. `afform/contactName/layout.html` displays a sub-form for editing first name, lastname, prefix, suffix, etc. | |
33 | 2. `afform/contactAddressess/layout.html` displays a sub-form for editing street addresses. | |
34 | 3. `afform/contactEmails/layout.html` displays a sub-form for editing email addresses. | |
35 | ||
36 | Next, we should create an overall `afform/contact/layout.html` which uses these building-blocks: | |
37 | ||
38 | ```html | |
39 | <div ng-form="contactForm"> | |
40 | <div crm-ui-accordion="{title: ts('Name')}"> | |
41 | <div afform-contact-name="{cid: routeParams.cid}"></div> | |
42 | </div> | |
43 | <div crm-ui-accordion="{title: ts('Street Addresses')}"> | |
44 | <div afform-contact-addresses="{cid: routeParams.cid}"></div> | |
45 | </div> | |
46 | <div crm-ui-accordion="{title: ts('Emails')}"> | |
47 | <div afform-contact-emails="{cid: routeParams.cid}"></div> | |
48 | </div> | |
49 | </div> | |
50 | ``` | |
51 | ||
52 | > *(FIXME: In the parent form's `meta.json`, we need to manually add `afformContactName`, `afformContactAddresses`, `afformContactEmails` to the `requires` list. We should autodetect these instead.)* | |
53 | ||
54 | What does this buy us? It means that a downstream admin (using APIs/GUIs) can fork `afform/contactName/layout.html` -- | |
55 | but all the other components can cleanly track the canonical release. This significantly reduces the costs and risks | |
56 | of manging upgrades and changes. |