Component Concepts
Linking
vs. Embedding Components
Form
Level Actions on Component Resources
Component
Level Actions on Form Resources
Editing
Forms Containing Components
Applying
CSS Style to components
Client
Javascript, Rich Client Features and the Client API
See also: Working
with Components, Working with Forms
A component is a collection of form elements e.g. fields,
tables, pages, controls etc, which can exist independently of a form.
Components can be added to any form in any project and are constructed in
exactly the same way as you would construct a form. Components support almost
all the facilities supported by forms including linked resources, field
mappings and links to scripts to perform processing logic. Components can also
be added to other components. Using components is an ideal way to promote reuse
of form elements between forms projects.
When creating a component you can choose one of the
following component types:
This component type is made up of
a sequence of one or more pages which can be added to a form at page level. For
example, you may want to have a standard sequence of user registration pages
which are used in a number of forms. These could be constructed as a multi page
component and inserted into the forms in question in the appropriate position.
This component type has no
visible elements and only contains fields, tables and texts. A fields &
tables component can be inserted onto the form itself. For example, you may have
a standard set of fields/tables which are used in different ways in different
forms but are always mapped in the same way to the same resources. Such a set
of fields/tables may be created as a fields & tables component and then
inserted into forms as required with the benefit of all mappings already being
in place.
A component may be added to a form in one of two ways:
If a component is embedded into a
form, a copy is made of all the constituent elements of the component and
inserted into the form. From this point hence, the component becomes just part
of the form and may be freely modified by the designer. Any changes to the
component will not be reflected in the forms into which it has previously been
embedded.
If a component is linked into a
form, the form simply acquires a reference to the component. In this case, the
designer can only make limited changes to the component in situ; however, any
changes made to the original component via the component editor can be deployed
to any form linking to it by clicking the deploy changes button on the
component toolbar. When editing a component, the designer may save the
component without impacting linked forms. When the designer is happy with the
component, s/he may deploy that component. Deploying a component causes any
changes to be propagated to all forms linked to it.
A designer may, at any time, convert a linked component to
an embedded component at which point, the form acquires a local copy of the
component, all change propagation benefits of linking are relinquished and the
designer is free to change the local copy of the component at will. Conversion
from embedding to linking is not possible in the same way although the designer
is free to delete all elements of the component and recreate the link.
When adding any component to a form, you are required to
provide a name prefix. This is necessary to enable multiple instances of the
same component to be inserted into the same form and to retain naming
uniqueness. The prefix may be anything meaningful to the user, for example, if
linking two instances of an address component, one for billing address and one
for delivery address, sensible prefixes might be BILLING_ and DELIVERY_.
These are prefixed to all names in that instance of the component within the
form (along with the component name itself) to aid recognition of where any
individual field, table, control, page etc came from.
So, for example, if we have a component called ADDRESS which contains a field called “FIRST_LINE”, and we insert this component into a form supplying the prefix “DELIVERY_”, the full field name in that instance of the component in the form will be “DELIVERY_ADDRESS__FIRST_LINE”. The Verj.io Studio will ensure uniqueness of these prefixes within a form and will warn you if a duplicate has been detected.
This mechanism also means that any scripts used in the component which refer to form elements - such as fields, tables, controls, texts, pages etc - in the component will function correctly when inserted into a form multiple times since the script will know which instance of the element it is referring to.
Components may only be deleted if they are not linked into
any forms. If you chose to delete a component, the system will notify you of
any forms which are currently linking to the component. If you are happy to
proceed with the deletion, all existing links will be automatically converted
to embeddings to remove any dependency on the component. The component may then
be safely deleted.
Components can be run in isolation just
like running forms. This causes the component to be temporarily embedded into a
dummy form and run in a browser to allow the designer to test the component’s
behaviour before adding it to forms or deploying any changes.
Note: Any scripts which refer to
elements outside the component will not work in this context.
(See Working with Components for more
information)
Scripts may be used in exactly the same way as for forms.
Typically these scripts will only refer to elements (such as fields, tables,
controls, pages, texts and resources) within the component itself. When the
component is inserted into a form, any references in the script will be applied
to the elements of that component instance only.
The following diagram shows a part-page component inserted
into a page twice, once with prefix PERSON1_ and once with prefix PERSON2_. The
script attached to the PERSON_1_TAX_CALC__EARNINGS field control will only
update the PERSON_1_TAX_CALC__TAX_TO_PAY field. The script attached to the
PERSON_2_TAX_CALC__EARNINGS field control will only update the
PERSON_2_TAX_CALC__TAX_TO_PAY field. This will happen automatically since the
script knows which component instance it belongs to and will only work within
that component’s context.
When a component exists in a different project from the form into which it is deployed, scripts may be overridden by creating a script with exactly the same name in the form’s project (or any other linked project).
When using the FPL language, overriding a script in this way
should be done with care since all references in a local script to field names
must be as they appear in the form itself… not as they appear in the
component. So, for example, if the script in the above example were to be
overridden in the MYFORM’s local project, the FPL for
the first component instance would be:
set PERSON_1_TAX_CALC__TAX_TO_PAY = PERSON_1_TAX_CALC__EARNINGS *
PERSON_1_TAX_CALC__TAX_RATE;
The rules for how references to form elements are resolved
during FPL script processing are as
follows. Please note that this applies only to form fields, and does not
include controls:
When using an API based
language such as Javascript and a script executes as part of an event
originating from a component (a component
level event), it has access only to elements within the component. This is
implemented as follows: the API variables fields,
tables, resources etc which are added to
each script only contain those elements which are part of the component. If a
component needs to access form level elements, it must do so by using the form variable; if a component needs to
access elements in another deployed component, it must do so via the components variable. In this way, a
component script normally only has access to elements within the component
itself, but can if required access all elements at form level by explicitly
coding this. Click here
for more details.
Components can include both static and dynamic lists in
exactly the same way as for forms.
(See Working with Lists for more
information).
A component can be linked to resources. Fields/tables in a
component may be mapped to resources in the Resources
View in exactly the same way as they would be in a form. This is referred
to as component-level mapping. When a component is inserted into a form,
the fields/tables may also be mapped to resources linked at form level. These
are referred to as form-level mappings.
(See Resources View and Field
Mappings for more information)
Component-level
mappings act within the context of an instance of a component only. When a
component is inserted into a form, the component’s resources are added to the
form but are only available to that instance of the component and can not be
edited from within the form. Any actions set on elements in the component will
act only on field mappings as set up in that component.
For
example: a component contains a table whose columns are mapped to a Database
Resource added to the component. The table also has a fetchtable command (API: Table.fetchTable())
as a before table event. When executed in the context of the form, this fetchtable will act based on the mappings set up in the
component and will fetch data from the resource configured in the component.
Only the table in this instance of the component will be updated. Any other
instances of this component will be unchanged.
Once a
component has been inserted into a form, its fields may additionally be mapped
to resources configured at form level. The result is identical to that for
regular form fields. This means that if an FPL command, such as a FETCH
<resource>, is performed from an element in the form which is not part of
the component, the event will update all fields mapped to this resource,
including those inserted from the component.
The diagram below shows a component called ADDRESS linked to
resource DB_A which has 2 fields POSTCODE and FIRST_LINE. The ADDRESS
component’s POSTCODE and FIRST_LINE fields are mapped to the DB_A resource’s POSTCODE
and FIRST_LINE fields respectively. The POSTCODE field has the immediate
validation option and fires an on change event which performs a fetch on the
DB_A resource. This means that when someone enters a post code, the FIRST_LINE
value will be fetched from the DB_A resource.
The ADDRESS component has then been inserted twice onto
PAGE_1 of the MYFORM form, once with a prefix of DELIVERY_ and once with a
prefix of BILLING_. With this form, if someone were to enter a delivery address
postcode, only the delivery address first line will be populated. If someone
enters a billing address postcode, only the billing address first line will be
populated. This is because the mappings have been made at component level.
In addition to this, the BILLING_ADDRESS__POSTCODE and
BILLING_ADDRESS__FIRST_LINE fields have also been mapped at form level to
resource DB_B. The form’s PAGE_1 has a before page event which pre-populates
the billing address based on some prior information by performing a fetch on
the DB_B resource. This fetch command will only act on the mappings made in the
form and so will only update the billing address’s form level field mappings.
(See Working with
Components for more information)
Component resources configured for each component prefix can be viewed in the Resources View panel.
For scripts at form level, it is also possible to act on resources
configured at component level by qualifying the resource name with the full
component prefix. For example, form MYFORM (in the figure above) could invoke a
FETCH action on the DELIVERY_ instance of the ADDRESS component’s resource DB_A
as follows:
fetch DB_A ( DELIVERY_ADDRESS );
This FPL command qualified the resource name with the component’s prefix with which it was inserted into the form. This will have the same effect as invoking the FETCH from within the component. The explicit nature of this qualifier implies that this syntax is only relevant in scripts local to the form and will be meaningless in a component since we don’t know what the prefixes are going to be!
Form level
scripts can invoke methods on a resource configured at component level by using
the components API variable e.g.:
components.DELIVERY_ADDRESS.resources.DB_A.fetch();
This technique can also be used to invoke methods on a resource belonging to a different deployed component. Click here for more details.
When executing a resource command from a component (e.g. fetch, sendmail etc) the system checks whether the script containing the command has been overridden. If it has, resources configured in the form are used, otherwise resources configured in the component are used.
Components
can invoke methods on a resource configured at form level by using the form API variable e.g.:
form.resources.DB_C.fetch();
Click here for more details.
When editing a form which contains linked component
instances, each linked component instance will be treated atomically (i.e. as a
whole, not as individual form elements). Any action requested on a subset of a
linked component instance will result in the system asking whether the action
may be applied to the entire component. If this is not appropriate, the action
may be aborted. For example, if a subset of a linked component is selected for
deletion, the system will display a list of all elements involved in that
component instance and prompt you whether you wish to delete the entire
component.
The majority of editable properties of elements of a linked component will appear read-only in the form since these are only configurable in the component itself. Page-type components linked into a form will appear completely read-only within the form and will again be treated atomically.
Exceptions to this rule are the following properties which
can be changed locally in a deployed component:
It is possible to associate a part-page component with a presentation template which in turn is linked to style sheets. However, this template is used only to facilitate the design process and is not used at runtime. At runtime, the presentation template for the form will be used and any advanced style configured using classes will be resolved from style sheets loaded via this template.
Note that
style-sheets can be applied to multi page components by using the Page Style
sheets property.
See the Client Javascript and Rich Client Features and Client API Guide pages for more information.
Client Scripts, Client Callable Functions, Html Element Properties and client-accessible Fields and Tables can be configured in both part page and multi page components. This allows rich-client units of work to be developed and then deployed into any number of forms and components. For example the ADDRESS component could allow a user to enter their postcode and press a ‘find my address’ button which would, perhaps using the Client API, perform a lookup based on that postcode and popup matching addresses for the user to select.
The Html Element Properties of the controls within a component can be overridden in the target form. Overriding the id and class Locators of these controls can be useful to resolve clashes with controls already in the Form and overriding, removing or adding new Event Handlers allows a form to customize the rich-client features inherited from the component.
When used by a component, the Client API must be triggered by an Event Handler or from a function in a Client Script which is in turn called by an Event Handler. If not then after the component has been inserted into a form the Client API may not find the Fields, Tables and Client Callable Functions requested.
Usage example - the component has a button (BUTTON1) and a Field (FIELD1). When BUTTON1 is clicked an alert is popped up containing the value of FIELD1.
alert($eb.getFieldValue(“FIELD1”));
function get(field) { return $eb.getFieldValue(field);
}
Use this function from the onclick Html Event Handler (again we could have used the click jQuery Event Handler), thus using the Client API indirectly:
alert(get(“FIELD1”));
The Client API looks up Fields and Tables in:
When performing an executeFunction command the Client API will look for the Client Callable Function in:
1. The target form, where the function will use form-level mappings. Thus Client Callable Functions in the form override ones inherited from a component.
2. The inserted component, as long as an Event Handler from the component triggered the Client API call (either directly or indirectly) and that Event Handler hasn’t been overridden. In this case the function will use component-level mappings.
Client Scripts configured in a part-page component are inserted into the page along with the component. When inserting a multi page component, Client Scripts in each page of the component stay with that page in the target form and those configured at the component level are added to the target form’s Client Scripts. The same Client Script can be inserted into the same page, or into the target form’s Client Script list more than once (via different components for example) but the generated HTML for that page will only contain one link to that Client Script.