Afform Core¶
The core of the Afform extension is an AngularJS module factory. Traditionally, to add a new AngularJS module
in CiviCRM, one must create an .ang.php
file, a js module file, some
controllers, components & templates, plus a page route to bootstrap AngularJS and load the module.
Afform Core does all that for you, all you need is a template .aff.html
file and an optional configuration .aff.json
file.
Creating a Form in an Extension¶
As an extension author, you can define a form along with its default, canonical content.
Simply create a file ang/MYFORM.aff.html
. In this example, we create a form named helloWorld
:
- Make sure you're in the directory with your extension (
cd /path/to/extension
) - Make an
ang
directory in your extension. (mkdir ang
) - Add some HTML/JS code to your
aff.html
file.echo '<div>Hello {{routeParams.name}}</div>' > ang/helloWorld.aff.html
- Add some JSON config to your
aff.json
file.echo '{"server_route": "civicrm/hello-world"}' > ang/helloWorld.aff.json
- Flush the caches so CiviCRM picks up the new form.
cv flush
A few things to note:
- The
ang
folder is the typical location for AngularJS modules in CiviCRM extensions. - We defined a route
civicrm/hello-world
. This appears in the same routing system used by CiviCRM forms. It also supports properties such astitle
(page title) andis_public
(defaults tofalse
). - After creating a new form or file, we should flush the cache.
- If you're going to actively edit/revise the content of the file, then you should navigate to Administer > System Settings > Debugging and disable asset caching.
- The extension
*.aff.html
represents an AngularJS HTML document. It has access to all the general features of Angular HTML (discussed more later). - In AngularJS, there is a distinction between a "module" (unit-of-code to be shared; usually appears as
camelCase
) and a "directive" (a custom HTML element; may appear ascamelCase
or askebab-case
depending on context). Afform supports a tactical simplification in which one*.aff.html
corresponds to one eponymous module and one eponymous directive.
Now that we've created a form, we'll want to determine its URL. As with most CiviCRM forms, the URL depends on the CMS configuration. Here is an example from a local Drupal 7 site:
We can use cv
to get full URLs for any civicrm/*
URL like so:
cv url "civicrm/hello-world"
returnshttp://dmaster.localhost/civicrm/hello-world
cv url "civicrm/hello-world/#/?name=world"
returnshttp://dmaster.localhost/civicrm/hello-world/#/?name=world
Open the URLs and see what you get.
Form Overrides¶
Afform files inside an extension (aka a "Packaged" form), are considered the default state, or "base".
If you fetch your form via API (e.g. the APIv4 Explorer), civicrm_api4('Afform', 'get')
will return something like this:
[
{
name: "helloWorld" // this corresponds to file name minus .aff.html extensions
server_route: "civicrm/hello-world" // as defined in helloWorld.aff.json
has_base: true,
has_local: false,
...
},
...
]
The calculated field 'has_base'
is true
because the Afform files are packaged in an extension.
'has_local'
is false
for now. However, site builders can modify your form without touching your extensnion code
simply by making a copy of the form in their local files directory. In that case the form would be considered overridden
and Afform would automatically use the local copy in favor of the one on your extension and the same api call would return
data from the new files with has_local: true
.