- A custom form lives in Automation Service Broker and overrides the default request form that VCF Automation generates from a Cloud Template input schema.
- Field values come from one of five sources: Constant, Bind, Computed, Conditional, External Value. External Value calls a VCF Operations Orchestrator action, and the action return type must match the field type.
- There are two validation layers: field constraints (live, per field) and external validation (an Orchestrator action that runs on submit and can fail the whole form).
- The single most common support ticket is a form that loads empty. The cause is almost always a required field with no default value feeding an external-value action.
- Keep form actions dumb and fast. Quota and placement belong in projects, policies and the template, not in the form.
Prerequisites: a released Cloud Template in the catalog (see Part 14), an Automation Service Broker role that can edit content, and an Orchestrator instance reachable from the org if you plan to use external values.
Mark one dropdown required, give it no default value, then bind it to an external-value action that fills in the field below it. Publish. The tenant opens the catalog item and sees a blank form that never populates, no error, no spinner, nothing. That exact pattern is the most frequent custom-form complaint I get called about, and it has nothing to do with the action code. The form designer is doing precisely what it was told. This Part is about telling it the right things.
Where custom forms actually live
When you publish a Cloud Template to the catalog, VCF Automation auto-generates a request form from the template inputs section. Every input becomes a field, the input type picks the widget, and any enum becomes a dropdown. That generated form is functional and ugly. A custom form is the override: you open the form designer in Automation Service Broker, switch the form on, and from that point the designer owns what the tenant sees. The underlying template inputs do not change, which matters because the same template can be requested through the API with no form involved at all.
This is a clean separation worth keeping in your head: the template defines what can be provisioned and what governance applies, the form defines how a human asks for it. Do not push provisioning logic into the form. The form is the storefront, not the warehouse.
VM Apps and All Apps draw the form from different places
In a VM Apps organization the experience is the one carried over from Aria Automation 8.x: the Service Broker custom form designer, the value sources you already know, and external values backed by an embedded or external Orchestrator. In an All Apps organization custom forms attach to blueprints through the Content Hub, and the org requires an external Orchestrator for external values. The field properties and validation concepts line up, but the navigation and a few capabilities differ. Confirm which org type you are in before you start clicking, because the menus do not match the older screenshots floating around the community.
The five value sources, and when each earns its place
Every field in the designer pulls its value, its option list, its constraints and its visibility from a value source. Pick the cheapest one that does the job. Reaching for External Value when a Constant would do is how forms get slow and brittle.
| Value source | What it does | Reach for it when |
|---|---|---|
| Constant | A fixed value baked into the form. | A default that never changes per request. |
| Bind | Mirrors another field on the form. | One answer should drive another field directly. |
| Computed | A value calculated from other fields, no code. | Simple arithmetic or string joins suffice. |
| Conditional | Sets value, options or visibility from rules. | Show or hide sections based on a prior choice. |
| External Value | Runs an Orchestrator action to return the value. | The data lives in an external system (IPAM, CMDB). |
External Value: wiring an Orchestrator action
The mechanism is simple. In the field Values tab, set the value source to External Value, then pick an Orchestrator action. The designer only lists actions whose return type matches the field type: a text field accepts actions returning a String, a multi-value field accepts an Array/string, and so on. Get the return type wrong and your action simply will not appear in the list. That is the first thing to verify when an action is missing.
Action inputs can be constants or bound to other fields. Constants are safe, because an empty string is passed when nothing is set. Bound inputs are where forms break. During form initialization a bound field with no default is null, your action receives null, and if it calls a method on that null it throws. Guard every bound input. Here is a name generator that defaults cleanly instead of failing:
// VCF Operations Orchestrator action: getDefaultVmName
// Return type: String (must match the form field type)
// Input: projectName (String), bound to the Project field
if (projectName == null || projectName == '') {
return 'vm-unassigned'; // never let a null reach .substring()
}
var prefix = projectName.substring(0, 4).toLowerCase();
return prefix + '-' + System.nextUUID().substring(0, 6);
// Bound input null on load => returns 'vm-unassigned'
// Project = 'Finance' => returns 'fina-a1b2c3'
Two validation layers, and why I prefer the cheap one
VCF Automation gives you two ways to keep bad input out of a deployment. They run at different times and cost different amounts.
Field constraints run live and for free
Required, min/max value, min/max length, regex pattern and match are properties on the field itself. They evaluate in the browser as the user types, with no Orchestrator round trip. A match constraint on a confirm-password field does the same job as a custom action and costs nothing. If a field constraint can express the rule, use it.
External validation runs on submit and can see the whole form
An external validation is an Orchestrator action wired in the form Validation tab. It runs when the user submits, can read several fields at once, and returns null for pass or an error string for fail. Use it for logic field constraints cannot express, like checking a request against a project ceiling or a policy. Do not use it for things a regex already handles.
// Orchestrator action: validateVmRequest (return type: String)
// Inputs: cpuCount (Number), memoryGB (Number) bound to form fields
// Returns null when valid, or an error message when not
var MAX_CPU = 16;
var MAX_MEM_GB = 64;
if (cpuCount == null || memoryGB == null) {
return null; // let the 'required' constraint handle empties
}
if (cpuCount > MAX_CPU) {
return 'CPU count ' + cpuCount + ' exceeds the project ceiling of ' + MAX_CPU + '.';
}
if (memoryGB > MAX_MEM_GB) {
return 'Memory ' + memoryGB + ' GB exceeds the ceiling of ' + MAX_MEM_GB + ' GB.';
}
return null;
| Field constraint | External validation | |
|---|---|---|
| Runs when | As the user types | On submit |
| Cost | None, in browser | One Orchestrator call |
| Scope | One field | Many fields, form-wide message |
| Best for | required, length, regex, match | policy / quota / cross-field rules |
Worked example: a clean "Request a VM" form
Take a template that exposes four inputs: project, environment, CPU and memory. A naive form marks all four required, binds a name generator to project, and adds external validations on CPU and memory. It loads slow and sometimes blank. Here is the version I would ship.
validateVmRequest, as a backstop. Result: two external calls on load instead of five, every field valid at render, and the ceiling enforced both in the field and on submit.The mistakes teams make
Four patterns account for most of the custom-form tickets I see:
1. Required fields with no default. Covered above and worth repeating because it is number one. If a field is required and feeds an action, give it a default.
2. Long chains of dependent actions. Field A feeds action B feeds field C feeds action D. One invalid link stalls everything after it, and it is miserable to debug. Break the form into pages and flatten the dependencies.
3. Heavy actions. Form actions should return in a second or two. They are not the place for large REST sweeps or database joins. If you need expensive data, fetch a narrow slice or pre-compute it.
4. Governance in the form. A clever validation that blocks a request is trivial to bypass through the API, which ignores the form entirely. Quotas, leases and approvals belong in projects and policies, not in form JavaScript.
A note for All Apps organizations
If you run an All Apps org, custom forms attach to blueprints through the Content Hub rather than the classic Service Broker content list, and external values require an external Orchestrator wired to the org. The value sources and the field-versus-external validation split behave the same way, so the design rules in this Part carry over. What differs is the path to the designer and a handful of capabilities that landed first in the VM Apps experience. When a community walkthrough does not match your screen, the org type is usually why. Part 3 covers the org-type decision in full.
Test the form before your tenants do
A custom form has more moving parts than it looks, and the only way to know it behaves is to request through it the way a tenant would. The catalog has a request preview, but a preview is not a submission. The behaviour I care about only shows up end to end: does every external value resolve on load, does each validation fire at the right moment, and does the request actually reach a deployment.
The check I run on every form before it goes near production tenants is short and always the same. Open the catalog item as a member of a real project, not as an admin, because role and project scope change which options the value sources return. Watch the network for how many Orchestrator calls fire while the form renders; one or two is healthy, a cascade is the dependent-action chain biting. Leave each required field at its default and confirm the dependent fields populate without a single click, because that is exactly the state a first-time user lands in. Then push each numeric field one past its ceiling and confirm both the field constraint and the external validation reject it, since you want the field constraint catching it live and the validation as the backstop. Last, submit a genuinely valid request and follow it to a running deployment, because a form that validates perfectly but never provisions is still broken.
One more habit worth keeping: export the form definition before any significant edit. The designer has no version history of its own, so the exported JSON is your rollback. When a change to a live catalog item misbehaves, re-importing the previous definition is far faster than reconstructing the layout field by field from memory while tenants are filing tickets.
What I'd Do
Start from the auto-generated form and change only what the tenant genuinely needs. Default every required field that feeds an action. Push validation down to field constraints wherever a regex or a min/max can carry it, and keep external validation for the cross-field and policy checks that constraints cannot express. Keep external-value actions small, guarded and fast, and count how many fire on load before you publish. Above all, remember the API does not see your form, so never let it be the only thing standing between a tenant and a bad deployment. Build your next catalog item this way and the support queue gets noticeably quieter. In Part 16 I move from the form to the rules behind it: approval, lease and day-2 governance policies.
References
Broadcom TechDocs — Custom forms in VCF Automation for VM Apps
Broadcom TechDocs — Custom forms in VCF Automation for All Apps
VCF Blog — Good Practices for Developing Custom Forms with VCF Automation



