Use built-in php function to do what we were trying to do with str_replace
[civicrm-core.git] / ext / afform / docs / embed.md
1 # Embedding Forms: Afform as reusable building-block
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
5 somewhere else -- e.g. as a dialog inside an event-listing or membership directory? Afforms are actually *re-usable
6 sub-forms*.
7
8 How does this work? Every `afform` is an *AngularJS directive*. For example, `hello-world` can be embedded with:
9
10 ```html
11 <div hello-world=""></div>
12 ```
13
14 Moreover, you can pass options to `helloWorld`:
15
16 ```html
17 <div hello-world="{phaseOfMoon: 'waxing'}"></div>
18 ```
19
20 Now, in `ang/helloWorld.aff.html`, you can use `options.phaseOfMoon`:
21
22 ```html
23 Hello, {{routeParams.name}}. The moon is currently {{options.phaseOfMoon}}.
24 ```
25
26 ## Example: Contact record
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. `ang/myContactName.aff.html` displays a sub-form for editing first name, lastname, prefix, suffix, etc.
33 2. `ang/myContactAddresses.aff.html` displays a sub-form for editing street addresses.
34 3. `ang/myContactEmails.aff.html` displays a sub-form for editing email addresses.
35
36 Next, we should create an overall `ang/myContact.aff.html` which uses these building-blocks:
37
38 ```html
39 <div ng-form="contactForm">
40 <div crm-ui-accordion="{title: ts('Name')}">
41 <div my-contact-name="{cid: routeParams.cid}"></div>
42 </div>
43 <div crm-ui-accordion="{title: ts('Street Addresses')}">
44 <div my-contact-addresses="{cid: routeParams.cid}"></div>
45 </div>
46 <div crm-ui-accordion="{title: ts('Emails')}">
47 <div my-contact-emails="{cid: routeParams.cid}"></div>
48 </div>
49 </div>
50 ```
51
52 And we should create a `ang/myContact.aff.json` looking like
53
54 ```json
55 {
56 "server_route": "civicrm/contact",
57 "requires" : ["myContactName", "myContactEmails", "myContactAddresses"]
58 }
59 ```
60 > *(FIXME: In the parent form's `*.aff.json`, we need to manually add `myContactName`, `myContactAddresses`, `myContactEmails` to the `requires` list. We should autodetect these instead.)*
61
62 We've created new files, so we'll need to flush the file-index
63
64 ```
65 cv flush
66 ```
67
68 and now we can open the page
69
70 ```
71 cv open 'civicrm/contact?cid=100'
72 ```
73
74 What does this buy us? It means that a downstream admin (using APIs/GUIs) can fork `ang/myContactName.aff.html` --
75 but all the other components can cleanly track the canonical release. This significantly reduces the costs and risks
76 of managing upgrades and changes.