ng-formality
v0.1.3
Published
Dynamic form generation system for productivity with Angular and Bootstrap 5
Downloads
4
Maintainers
Readme
Introduction
Formality
is a form builder built with Angular. It uses Angular's Reactive Forms and ng-bootstrap (Bootstrap 5). Formality
supports a variety of control Types.
Goals
- Improve scalability.
- Ease front-end developer workload if the form is dynamic, and its structure is defined in the backend. Unless a distinctive styling for a control is needed, there should be no additional effort needed to CRUD a control in the front-end.
- Keep website forms' layout and styling consistent.
- Reuse the logic of rendering forms.
- Keep website modular by having forms rendering and forms' data seperate.
Additionaly, FormalityUtils
class provides additional functions:
- Generate styling template for your unique form structure
- Object structure validity checking
Note:
FormalityUtils
currently generates SCSS styling template only.
Types
Text
Password
Email
Number
Search
Mobile
-tel
input type.Url
Textarea
Article
- a rich WYSIWYG text editor that uses ngx-quill package.Checkbox
- can be intermediate.Switch
- same asCheckbox
but displayed as switch. Cannot be intermediate.Radio
RadioGroup
Range
Date
Select
- a drop down with several values. Can be single, or multi. It uses ng-select package.Country
- a drop down with country name and their flags.File
Image
Form
- used in order for controls to be grouped in the DOM tree, and to be grouped in Angular'sFormGroup
.Group
- used in order for controls to be grouped in the DOM tree.
Data structure
You may define the object as a JSON
, typescript
object, or receive it from the backend. The object is constrained by abstract FormalityControl
type, which can be nested.
Additional constraints:
- A
Group
must havecontrols
property and must not havevalue
property. - A
RadioGroup
must have bothvalue
andcontrols
properties. - All other controls, including FormGroup, must have
value
property and shouldn't havecontrols
property. - No identical parent and child name combinations within a form or within all active
Formality
forms.
Any FormalityControl
value may be in form of a control or array of controls, including the base object, allowing you to wrap your form elements inside a single group or keep them seperate in the DOM tree.
Form controls' classes
Formality creates a DOM tree with css
selectors in a predictable manner:
- Form:
{control.name}-form form
class.- Controls:
{control.name}-controls controls
class.- Control:
{control.name}-control
class (also{control.name}{parent.name}
id). - Label:
{control.name}-label
class.
- Control:
- Controls:
You can use that to make unified style for your forms by selecting subform
and controls
, and/or make distinctive styles by selecting controls by their name.
Formality
adds is-valid, is-invalid classes according to control's validity.
Usage
1. Define your form.
form1.json
:
{
"label": "Formality - optimise productivity!",
"name": "baseGroup",
"type": "group",
"controls": [
{
"name": "yourAge",
"label": "Whats your age",
"value": "10",
"type": "text",
"validators": {
"required": true,
"minlength": 2
}
},
{
"name": "simpleSwitch",
"label": "Do you like switches?",
"value": false,
"type": "switch",
"validators": {
"requiredTrue": true
}
}
]
}
2. Pass the object to FormalityComponent
.
Give form an
id
if you're going to style multiple forms differently.
<formality class="col-lg-6 col-12" id="test1" [formData]="form1"> </formality>
3. Use FormalityUtils
class to get .scss
styling template.
console.log(FormalityUtils.generateScssSnippet(form1, SnippetType.Specific));
Copy and paste the code to styles.scss
(or a file, included in styles.scss
for better seperation). If you want to make sure styles for common selectors like subform
and controls
only impact this form - wrap it inside your id
. In this case - it is test1
. Format the snippet. Result:
#test1 {
.baseGroupsubform {
.baseGroupcontrols {
.yourAge {
}
.simpleSwitch {
}
}
}
}
Add styling as you see fit.
4. Subscribe to form submittions.
@ViewChild(FormalityComponent) form: FormalityComponent;
form.onSubmitted.subscribe((value) => console.log(value));
5. Introduce restrictions checking (Optional)
FormalityUtils.checkDataValidity(form1);
Bootstrap integration improvement
A inconsistency within bootstrap is that for some control types bootstrap has the following layout:
label control
but for other, such as a checkbox layout is reversed:
control label
In ng-formality we render all controls using the latter, with the help of a flexbox and an order attribute when needed. That allows the code of FormControlComponent
to be simpler. However, styling of valid/invalid control is missing for some control labels.
Thus, you should add the following code in _forms.scss
of ng-bootstrap file if you want all invalid control labels to be highlighted.
.form-control {
@include form-validation-state-selector($state) {
~ .form-label {
color: $color;
}
}
}
FAQ
- This library is tied to Bootstrap. Is it not going to make all my websites look the same?
No. There are many bootstrap theme collection websites available online. Make sure it is Bootstrap 5 and replace the style sheets to have completely different look with minimal effort.
Future improvements
- Support for FormArray.
- Support prefilling image field.
- Add option to keep image file name.
- Support mobile number input by displaying country's flag, country's mobile code dropdown next to an input field.
- Seperate
date
,time
anddatettime
types (or add options to existing control). - Extend
Select
types to be capable of holding a value different than its name. - Use moment to format date. Add ability to pass format.
- Add range and select validity check in
FormalityUtils
. - Add ability to have a select with labels and values different from labels, just like with
RadioGroup
type. - Extend
FormalityUtils
to generate SASS template. - Option for an image to be displayed when uploaded.
- Solve dependancy on ngx-translate.
- Create a online tool for generating style sheet templates.
- Perhaps remove
Radio
type because this type is certain by being in aRadioGroup
type parent. - Perhaps implement lazy loading for
CountrySelect
type, as it will be more rarely used and requires loading countries flags. - Perhaps bootstrap control classes by Cascading Style Sheet's
@extend
keyword, instead of Angular's[class]
binding would give more flexibility. - Perhaps add ability to pass
FormalityComponent
when generating stylesheet, in order to include its ID. - Support partial editted form values for ability to send
PATCH
requests. - For more optimised
POST
requests with binary files, implement value conversion to FormData (multipart/form-data) type.
PRs are welcome!