Forms angular comes with a small number of forms that can be used - sometimes with small amendments - to meet a vast number of requirements. They all use RESTful routes and handle querying and updating the server
For each model the following routes are supported:
The form-input directive expands the schema into nice looking data capture form, but that is only a small part of the story. The basic edit form also gives you:
Buttons to perform the usual Save, Cancel, New and Delete operations. forms-angular handles all the back-end stuff for you.
The form button customisation is currently limited to over-riding the default enabled state of the buttons by defining functions in a controller for the model (or model and form). See here for an example.
The listing routes (of the format /#/:model) are used to build a page containing a list of documents in the collection, showing the list fields. You can specify a sort order by adding a listOrder value to the model as shown in this model. Alternatively you can specify a sort order at run-time using the o parameter as in this example.
Listing routes support filters, such as
/#/b_using_options?f={"surname":"Smith"}
and calls to the aggregation framework, provided they project to an array of docs that contains an _id property which is used to select from the model. For example the (rather unpalatable)
/#/f_nested_schema?a=[{"$unwind":"$exams"},{"$sort":{"exams.score":1}},{"$group":{"_id":{"id":"$_id"},"bestSubject":{"$last":"$exams.subject"}}},{"$match":{"bestSubject":"English"}},{"$project":{"_id":"$_id.id"}}]
selects all students who did better in their English exam than any other subject. To find out how to use the aggregation framework refer to the MongoDB docs.
These can be combined (though there appears to be a problem unless the filter precedes the aggregation).
By default the list order is the MongoDB natural order. The default list order for a table can be set by specifying a listOrder option in the model definition (see g_conditional_fields for an example).
The smallest form is the search form, in the navbar at the top of this page. When you enter text into it the SearchCtrl controller makes a call to the server which looks for matching data by searching the indexed fields in each model for values starting with the search string.
There are a number of options that can be added to model exports to modify the search behaviour. Examples can be found in the model definitions files for f_nested_schema and g_conditional_fields.
DataFormHandler.getResource('person').options.localisationData = [{from: 'person/customer', to: 'person/client', context: 'resource'},{from:'Customer', to:'Client', context: 'resourceText'}];
.
The formstyle attribute can take the values vertical, horizontal, inline and horizontalCompact. The first three generate the markup for a Twitter Bootstrap 2 style and the last slightly modified style. vertical generates markup that works with the default form style, and the others needs classes adding as follows:
formstyle | Associated Bootstrap class(es) |
---|---|
horizontal | form-horizontal |
horizontalCompact | form-horizontal compact |
inline | form-inline |
Sub forms that are created by the directive will have these classes added in the appropriate place.
Additional functionality can be added by using "model controllers" which have the name of a model followed by Ctrl (or the name of the model followed by the name of the custom form followed by Ctrl. There is an sample model controller here which is used in the examples in this section. The NavCtrl controller handles the model controllers, so don't remove it.
The BaseCtrl scope has a variable called modelNameDisplay which is used in several places in the demo app. It defaults to the model name in title case, but can be over-ridden in the model controller.
The menu can be added to where required by the models (see an example here) The options can be configured to appear when records are being listed, edited or created. The top level text is taken from the model controller's dropDownDisplay variable, if present. If not present it will fall back to the modelNameDisplay (see above) and it that is not present the model name.
The form-input directive broadcasts a formInputDone message when it has processed a control. This can be acted on by the model controller. In our example we add a change handler to a select2 control which changes background color of a control group when the eye colour is changed.
There are hooks before and after CRUD events as follows:
In all onBefore... cases passing an error back will stop the event completing. There is a trivial example of how a data event hook might be used in this controller, which shows how such event handlers are set up.
You can also call onRecordChange function(data, old) which is useful for updating calculated fields etc.
It is possible to apply additional attributes to all elements of a certain type by passing it once in the form-input declaration. The available types are Control Group, Field or Label.
This can be achieved in two ways. Either as an attribute of the form-input element:
<form-input schema="formSchema" add-all-group="injected-element='with parameters'">
or via the controller by making it an attribute of scope:
$scope.addAllGroup="injected-attribute"
The three versions of this are:
For example if wished to inject a directive called 'hide-on-empty' to every individual control group then you would add:
add-all-group="hide-on-empty"
to the form-input declaration.
If declared in a controller then it will be applied to all child controllers. If declared in the form-input element the scope is limited to the individual form's scope. In this way a single declaration at the root scope is seem by all controllers.
Due to the parse method, in order declare multiple classes each class must be prefixed with 'class=' e.g.
<form-input schema="formSchema" add-all-group="injected-element='with parameters' class=myclass class=my-second-class">
On the server side there are hooks around data events as follows:
There are examples of both in this model