-
Notifications
You must be signed in to change notification settings - Fork 4
cdo.form_and_model_generators
org.nasdanika.cdo
bundle provides several classes for generating Bootstrap/AngularJS/KnockoutJS forms and models from EClass and EOperation metadata
and annotations:
-
FormGeneratorBase - Abstract base class. It has a number of protected methods which can be overriden by subclasses to fine-tune form
generation. Default method implementations use metadata such as feature/parameter name and type and annotations to generate forms.
- EClassFormGenerator - Generates HTML/Bootstrap form from EClass metadata and annotations.
- EOperationFormGenerator - Generates HTML/Bootstrap form from EOperation metadata and annotations.
-
AngularJsFormGeneratorBase - Abstract base class for generating forms and models to work with AngularJS.
- AngularJsEClassFormGenerator - Generates HTML/Bootstrap AngularJS form and model from EClass metadata and annotations.
- AngularJsEOperationFormGenerator - Generates HTML/Bootstrap AngularJS form and model from EOperation metadata and annotations.
-
KnockoutJsFormGeneratorBase - Abstract base class for generating forms and models to work with KnockoutJS.
- KnockoutJsEClassFormGenerator - Generates HTML/Bootstrap KnockoutJS form and model from EClass metadata and annotations.
- KnockoutJsEOperationFormGenerator - Generates HTML/Bootstrap KnockoutJS form and model from EOperation metadata and annotations.
Annotations used by the generators are:
-
org.nasdanika.cdo.web.html.form-control
for EClass features - attributes and references (by default controls are not generated for references) and for EOperation parameters. This annotation supports the following details keys:-
attribute:<attribute name>
- Allows to specify control attribute. -
group-attribute:<attribute name>
- Allows to specify group attribute. -
control-id
- Control ID, defaults to<feature|parameter name>_control
. -
default
- Default value. If not set then attribute default value is used for attributes. -
help-text
- Help text. No default. In AngularJS generators help text is used to display control-level validation messages.-
inline
- Inline checkbox control if set to true.
-
-
input-type
- One of InputType values. Default value is computed from feature/parameter type bygetInputType()
methods which can be overriden. -
label
- Control label. Defaults to feature/parameter name split by camel case with the first word capitalized and the rest uncapitalized. E.g. a label foruserName
parameter or feature would be "User name". -
placeholder
- Control placeholder for controls which support placeholders. Default is the same as for label. -
private
- Iftrue
then feature/parameter is not included into the generated form. -
required
- Marks the generated control as required if set totrue
. -
style:<style name>
- Allows to customize control style. E.g.style:background
->yellow
-
group-style:<style name>
- Allows to customize group style. -
validator
- Control validator used by AngularJS and KnockoutJS generators. The value of thevalidator
details key shall be a JavaScript function body returning validation message or a promise for a validation message. If the return value is falsey, e.g. undefined or an empty string, then validation is successful, otherwise the return value is displayed as a control-level error message. The function body has access to the control value throughvalue
parameter and to the whole model throughthis
.
-
-
org.nasdanika.cdo.web.html.form
for EClasses and EOperations. This annotation supports the following details keys:-
model
- Object declarations to add to the model definition, e.g. helper functions. -
validator
is used by AngularJS and KnockoutJS generators in generation ofvalidate()
model function. The value of thevalidator
details key shall be a JavaScript function body returning validation message or a promise for a validation message. If the return value is falsey, e.g. undefined or an empty string, then validation is successful, otherwise the return value is displayed as a form-level error message. The function body has access to the model data throughvalue
parameter and to the whole model throughthis
.
-
AngularJS generators have generateModel()
method which returns JavaScript object definition with the following entries:
-
data
- an object which is either empty or contains default values for features/parameters. Form controls are bound to this object's entries. For existing object replace the generateddata
entry with the JavaScript API object. -
createData()
- a function returning a fresh data object either empty or with default values. -
clear()
- this function sets model data to a fresh object and empties validation results. -
validationResults
- an empty object to hold validation messages for controls. -
validate()
- a function which invokes validators for controls and the form and returns a promise of boolean value. If the promise is resolved withtrue
then the form is valid. -
apply(target)
- this function is generated byAngularJsEOperationFormGenerator
. It invokes the target passing model data as arguments in the order in which they are defined in the ECore model. Iftarget
is an object with<operation name>
function, then that function is invoked, otherwisetarget
assumed to be a function to be invoked. -
validateAndApply(target)
- this function is generated byAngularJsEOperationFormGenerator
. It invokesvalidate()
. If validation is successful, then it invokesapply(target)
.validateAndApply
returns a promise resolved with return value ofapply()
or rejected with{ validationFailed: true[, validationResults: ...] }
if client side or server side validation failed, or{ targetInvocationError: <target rejection reason> }
. This function expectstarget
function to return a promise, which is the case for JavaScript API functions generated for model objects' EOperations.
KnockoutJS generators have generateModel()
method which returns JavaScript constructor function definition with the following entries:
-
data
- a property with getter and setter. The setter copies entries from the value to observables, the getter returns an object with its properties having getters and setters bound to observabled. -
observableData
- an object with observables linked todata
entries. Form controls are bound to this object's entries. -
clear()
- this function sets model data undefined/default values and empties validation results. -
validationResults
- a property similar todata
setting and returning validation results. -
observableValidationResults
- an object with observables to which form error messages are bound. -
validate()
- a function which invokes validators for controls and the form and returns a promise of boolean value. If the promise is resolved withtrue
then the form is valid. -
apply(applyTarget)
- For EOperations it invokes
applyTarget
passing model data as arguments in the order in which they are defined in the ECore model. IfapplyTarget
is an object with<operation name>
function, then that function is invoked, otherwiseapplyTarget
assumed to be a function to be invoked. - For EClasses it sets
applyTarget
properties to data entries, then invokesapplyTarget.$store
function, and returns its return value.
- For EOperations it invokes
-
validateAndApply(applyTarget)
- Invokesvalidate()
. If validation is successful, then it invokesapply()
.validateAndApply
returns a promise resolved with return value ofapply()
or rejected with{ validationFailed: true[, validationResults: ...] }
if client side or server side validation failed, or{ targetInvocationError: <target rejection reason> }
. This function expectsapplyTarget
function to return a promise, which is the case for JavaScript API functions generated for model objects' EOperations and$store
function. -
loadModel(source)
is generated for EClasses only. It loads data fromsource
to observables and can be invoked to refresh views.
Nasdanika WebTest Hub user management application consists of a table listing existing users, Add button to create users, and a dialog for creating/updating users.
The create/update dialog has a different title depending on whether it shown to create or update a user. In update mode login text input is disabled. If authentication is "Password" then "Password" and "Password confirmation" fields are displayed and are required in create mode.
The dialog model validates that a login for a new user does not already exists and that password and password confirmation match in the authentication mode is "Password".
In this application the dialog and the model are generated from a createOrUpdateUser()
EOperation metadata and annotations:
.
The application template is generated by the usersApp() method, which uses AngularJsEOperationFormGenerator (line 725) to generate a form (line 732) and a model, which is passed to the controller generator (line 745).
When the controller is loaded data into the table is retrieved from userList
hub
property generated from userList
operation with getter
annotation:
After that the table is updated with data returned by deleteUser()
and createOrUpdateUser()
functions.
In the controller template
the form model is injected into $scope
at line 41.
The controller's createOrUpdateUser()
function (line 57) is invoked on form submission.
$scope.createOrUpdateUser = function() {
showFormOverlay();
$scope.userModel.validateAndApply(hub).then(
function(userList) {
$scope.$apply(function($scope) {
$scope.userList = userList;
hideFormOverlay();
jQuery("#createUpdateUserFormModal").modal('hide');
});
},
function(reason) {
if (reason.validationFailed) {
$scope.$apply();
} else {
console.trace(reason);
alert(reason.targetInvocationError ? reason.targetInvocationError : reason);
}
hideFormOverlay();
}).done();
}
The function displays an overlay div over the form to provide a visual cue that there is a server interaction in progress and to prevent
user interaction with the dialog. Then it invokes generated validateAndApply()
function with hub
argument. validateAndApply
returns
a promise. If the promise is resolved, $scope.userList
is set to the promise fulfillment value. If the promise is rejected due to
validation problems, then $scope.$apply()
is invoked to display error messages. Otherwise, an alert is displayed.
validateAndApply()
invokes (also generated) hub.createOrUpdateUser()
, which in turn invokes Hub.createOrUpdateUser()
operation
on the server.
- Create a route method to generate the application template (
usersApp
). - Create data retrieval operation(s), if required. If parameterless, annotate them as getters. In the hub user management example the data
retrieval operation is used because
isAdmin
andauthentication
are computed properties. Otherwisehub.users
reference could have been used. - Create data modification operations. These operations may return the same data as data retrieval operation(s).
- Create a controller template. Controller methods shall delegate validation and data submission to the generated functions.
- Add forms generated from the operations into the application template, and models into the controller.