@smartbit4all/form
v1.7.15
Published
Stable version: 1.6.8
Downloads
58
Keywords
Readme
Smart Form
Stable version: 1.6.8
References
These packages must be updated in case of a new version:
How to use
Installation
Go to your project, open the terminal and use the following command:
npm i moment
npm i @angular/[email protected]
npm i @angular-material-components/[email protected]
npm i [email protected]
npm i @smartbit4all/form
Then import it in the AppModule:
app.module.ts:
import { SmartformModule } from '@smartbit4all/form';
...
@NgModule({
declarations: [...]
imports: [
...
SmartformModule,
]
...
})
Usage
example.component.html
<div *ngIf="form">
<smartform #smartFilter [smartForm]="form"></smartform>
</div>
example.component.ts
// smartFilter
@ViewChild("smartFilter") smartFilterChild!: SmartformComponent;
form!: SmartForm;
model?: RegistrationForm;
myValidator(group: any): ValidatorFn {
return fieldMatchingValidator(
group,
"registrationData.password",
"registrationData.confirmPassword"
);
}
constructor() {
this.constructForm();
}
async constructForm(): Promise<void> {
this.model = await this.apiCall();
let nationalities: any = {
europe: {
displayValue: "Europe",
countries: [
{
displayValue: "Hungarian",
objectUri: "hungarian",
},
{
displayValue: "German",
objectUri: "german",
},
],
},
northAmerica: {
displayValue: "North America",
countries: [
{
displayValue: "American",
objectUri: "usa",
},
{
displayValue: "Canadian",
objectUri: "canada",
},
],
},
};
this.form = {
direction: SmartFormWidgetDirection.COL,
model: this.model,
useOnValueChangeEvent: true,
useOnBlurEvent: true,
validators: [
{
validator: this.myValidator.bind(this),
errorMessage: "The passwords are not the same",
name: SmartValidatorName.fieldMatchingValidator,
},
],
widgets: [
{
key: "registrationData.email",
label: "Email",
type: SmartFormWidgetType.TEXT_FIELD,
showLabel: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
isCustom: false,
name: "required",
},
{
validator: Validators.email,
errorMessage: "This is not a valid email",
isCustom: false,
name: "email",
},
],
},
{
key: "registrationData.password",
label: "Password",
type: SmartFormWidgetType.TEXT_FIELD,
showLabel: true,
isPassword: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
{
validator: Validators.minLength(8),
errorMessage: "The password must be at least 8 characters",
name: SmartValidatorName.minLength,
},
],
},
{
key: "registrationData.confirmPassword",
label: "Confirm password",
type: SmartFormWidgetType.TEXT_FIELD,
showLabel: true,
isPassword: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
{
validator: Validators.minLength(8),
errorMessage: "The password must be at least 8 characters",
name: SmartValidatorName.minLength,
},
],
},
{
key: "registrationData.phone",
label: "Phone",
type: SmartFormWidgetType.TEXT_FIELD,
showLabel: true,
mask: "+00-00-000-0000",
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
{
validator: this.phoneNumberValidator("36"),
errorMessage: "This is not a valid phone number",
isCustom: true,
name: "validPhoneNumber",
},
],
},
{
key: "registrationData.dateOfBirth",
label: "Date of birth",
type: SmartFormWidgetType.DATE_PICKER,
showLabel: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
],
},
{
key: "registrationData.nationality",
label: "Nationality",
type: SmartFormWidgetType.SELECT,
showLabel: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
],
valueList: Object.keys(nationalities).map((key: string) => {
return {
key: key,
label: nationalities[key].displayValue,
type: SmartFormWidgetType.ITEM_GROUP,
valueList: nationalities[key].countries.map((value: Value) => {
return {
key: value.objectUri,
label: value.displayValue,
type: SmartFormWidgetType.ITEM,
value: value.objectUri,
};
}),
};
}),
},
{
key: "registrationData.interests",
label: "Interests",
type: SmartFormWidgetType.TEXT_FIELD_CHIPS,
showLabel: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
],
},
{
key: "tos",
label: "Terms of Services",
type: SmartFormWidgetType.CHECK_BOX,
showLabel: true,
validators: [
{
validator: Validators.required,
errorMessage: "This field is mandatory",
name: SmartValidatorName.required,
},
],
valueList: [
{
key: "tos",
label: "Terms of Services",
type: SmartFormWidgetType.ITEM,
},
],
},
{
key: "subscribeToNewsletter",
label: "Newsletter",
type: SmartFormWidgetType.TOGGLE,
},
],
};
}
submit(): void {
this.form = this.smartFilterChild?.submitForm();
}
Using multiple languages - i18n
The labels of the form can be translated to any languages that your application supports, all you have to do is providing a service to the form (ideally the TranslateService exported from @ngx-translate/core).
The SmartForm requires a SmartTranslateService which contains some very basic functions:
export interface SmartTranslateService {
get(key: string | Array<string>, interpolateParams?: Object): Observable<string | any>;
get onLangChange(): EventEmitter<any>;
get currentLang(): string;
set currentLang(currentLang: string);
instant(key: string | Array<string>, interpolateParams?: Object): string | any;
}
Example:
en.json:
{
"username": "Username",
"password": "Password",
...
}
hu.json:
{
"username": "Felhasználónév",
"password": "Jelszó",
...
}
any.component.ts:
import { TranslateService } from "@ngx-translate/core";
...
export class AnyComponent {
form: SmartForm;
constructor(private translate: TranslateService) {
this.translate.addLangs(["en", "hu"]);
this.translate.setDefaultLang("hu");
this.constructForm();
}
constructForm(): void {
let model: any = {
username: "",
password: "",
language: "",
};
let possibleValues: any[] = [
{
displayValue: "hungarian",
objectUri: "Hungarian",
},
{
displayValue: "english",
objectUri: "English",
},
];
this.form = {
direction: SmartFormWidgetDirection.COL,
model,
translateService: this.translate, // The TranslateService is provided here
widgets: [
{
key: "username",
label: "username",
placeholder: "username",
type: SmartFormWidgetType.TEXT_FIELD,
},
{
key: "password",
label: "password",
type: SmartFormWidgetType.TEXT_FIELD,
},
{
key: "language",
label: "language",
type: SmartFormWidgetType.SELECT,
valueList: possibleValues.map((value: any) => {
return {
key: value.objectUri,
label: value.displayValue,
type: SmartFormWidgetType.ITEM,
value: value.objectUri,
};
}),
},
],
};
}
toggleLanguage(): void {
this.translate.use(
this.translate
.getLangs()
.filter((lang: string) => lang !== this.translate.currentLang)[0]
);
}
}
Version logs
@smartbit4all/form v1.6.3
Type: Bugfix
A bug has been fixed which caused that the invalidFields property did not become undefined
automatically if the form was valid.
@smartbit4all/form v1.6.2
Type: Update
The SmartLabel got a new property which allows to mark that as required.
export interface SmartLabel {
...
markAsRequired?: boolean;
}
@smartbit4all/form v1.6.0
Type: Update
This version contains major updates and fixes.
SmartFormWidget - type specific intellisense and type check
The SmartFormWidget became a type declaration:
export declare type SmartFormWidget<T> =
| SmartTextField<T>
| SmartTextFieldNumber<T>
| SmartTextFieldChips<T>
| SmartTextBox<T>
| SmartSelect<T>
| SmartSelectMultiple<T>
| SmartCheckBox<T>
| SmartRadioButton<T>
| SmartDatePicker<T>
| SmartDateTimePicker<T>
| SmartContainer<T>
| SmartLabel
| SmartTime<T>
| SmartToggle<T>
| SmartIndicatorItem;
All the types above have one property in common which is type: SmartFormWidgetType. By declaring the type of the widget the intellisense only shows those properties which are available.
SmartIndicatorItem
The SmartForm got a new widget that can be used for password strength indicator.
export interface SmartIndicatorItem {
type: SmartFormWidgetType.INDICATOR;
key: string;
label: string;
originalLabel?: string;
showLabel?: boolean;
indicator: SmartIndicator;
isVisible?: boolean;
cssClass?: string;
}
export interface SmartIndicator {
indicateProperty: string;
indicatorLength: number;
indicatorStatusLabels: string[];
originalIndicatorStatusLabels?: string[];
indicatorValue: number;
changeIndicatorStatus: (valueToCheck: string) => number;
}
SmartValidator - icons
The SmartValidator got two new properties for setting custom icon and it's color to an error.
export interface SmartValidator {
...
icon?: string;
iconColor?: string;
}
@smartbit4all/form v1.5.0
Type: Update
From now on the SmartForm can be used in multi language applications by default.
@smartbit4all/form v1.4.12
Type: Update
The max size of each files can be set for SmartFileUploader.
@smartbit4all/form v1.4.10
Type: Update
In order to attract the user's attention to the invalid fields of the form, the submitForm() function can return a SmartFormInvalidFields
object, which contains the name and keys of all the invalid fields.
export interface SmartFormInvalidFields {
invalidFieldNames: string[];
invalidFieldKeys: string[];
}
Type: Bugfix
The TEXT_FIELD_CHIPS had a bug validation bug.
@smartbit4all/form v1.4.9
Type: Update
Autofocus is disabled due to an issue.
This is the validator update, in which the validation of the form was rethinked.
The SmartFormWidget
and the SmartForm
both got a new property:
validators?: SmartValidator[];
A SmartValidator looks like this:
export interface SmartValidator {
validator: ValidatorFn;
errorMessage?: string;
name: SmartValidatorName | string;
}
The name refers to the property name of the object returned by the validator. To make this easier, the SmartValidatorName
enum contains all the validators supported by the SmartForm
by default.
export enum SmartValidatorName {
// Angular validators
required = "required",
requiredTrue = "required",
email = "email",
max = "max",
maxLength = "maxlength",
min = "min",
minLength = "minlength",
pattern = "pattern",
passwordValidator = "passwordValidator",
// Custom validators
fieldMatchingValidator = "fieldsMatch",
}
@smartbit4all/form v1.4.7
Type: Update
Autofocus property added to SmartFormWidget
.
@smartbit4all/form v1.4.6
Type: Update
onValueChange event added to TEXT_FIELD_NUMBER widget.
@smartbit4all/form v1.4.5
Type: Bugfix
Text field chips bugfix.
@smartbit4all/form v1.4.3
Type: Update
Date time picker widget has been introduced.
@smartbit4all/form v1.4.2
Type: Bugfix
A bug with the Toggle widget has been fixed.
@smartbit4all/form v1.4.1
Type: Update
Version 1.4.0 contains major updates which improves the usability of the SmartForm
.
Updates:
- complex data structure support
- constraints
- text field masking
- label style update
Complex data structure support:
From now property path as the key of the widget works with complex models:
let model = {
id: "random_id",
data: {
username: "user's name",
}
}
let form: SmartForm = {
direction: SmartFormWidgetDirection.COL,
model,
widgets: [
{
key: "id",
label: "Id",
type: SmartFormWidgetType.TEXT_FIELD,
},
{
key: "data.username",
label: "Username",
type: SmartFormWidgetType.TEXT_FIELD,
},
]
};
Constraints:
The SmartFormComponentConstraint
type has been introduced. Generic settings such as visibility, mandatoriness and enablement can be injected into the SmartForm and applied by key.
export interface SmartFormComponentConstraint {
/**
* The data name to identify the related component or componenets. If it is a path the format is the following - dataSheet.field.
*/
dataName?: string;
visible?: boolean;
mandatory?: boolean;
enabled?: boolean;
}
Text field masking:
Text fields can be masked with a simple string.
SmartFormWidget for phone numbers (Hungarian):
{
key: "phoneNumber",
label: "Phone number",
type: SmartFormWidgetType.TEXT_FIELD,
mask: "+00-00-000-0000",
},
@smartbit4all/form v1.3.7
Type: Features
This version add onValueChange event to TEXT field SmartformWidget.
@smartbit4all/form v1.3.5
Type: Features
This version introduces the isVisible?: boolean
property, and also supports to show icons in Selects.
@smartbit4all/form v1.3.2
Type: Update
The labels of the widgets were updated. The SmartForm model got a labelTheme
property which is applied to the labels. The labelTheme
should be a theme defined by MaterialTheme.
@smartbit4all/form v1.3.1
Type: Features
From now on the <smartformwidget></smartformwidget>
always has a CSS class which is the key of the widget.
@smartbit4all/form v1.3.0
Type: Features
This version contains two important updates:
- Detecting CapsLock in password fields
- Submitting the form using enter
The changes in the models are the followings:
export interface SmartForm {
...
submitOnEnter?: () => void;
}
export interface SmartFormWidget<T> {
...
capsLockWarning?: string;
capsLockWarningIcon?: string;
}
@smartbit4all/form v1.2.9
Type: Bugfix
The min value of SmartFormWidgetType.TEXT_FIELD_NUMBER
used to be a static 10.
@smartbit4all/form v1.2.8
Type: Bugfix
Previously the SmartFormWidgetType.SELECT
used to emit onBlur events, however it was not supposed to. From now on it only emits onValueChange events.
@smartbit4all/form v1.2.7
Type: Update
@smartbit4all/icon
support.
@smartbit4all/form v1.2.6
Type: Update
This update contains date issue fixes for the DATEPICKER widget. The hint for the datePicker can be injected when creating the widget with the dateFormatHint
property.
export interface SmartFormWidget<T> {
...
dateFormatHint?: string;
}
Using custom locales became more easy, just paste the following line with the correct locale into the providers in app.module.ts
:
app.module.ts:
@NgModule({
...
providers: [
...
{ provide: MAT_DATE_LOCALE, useValue: "hu-HU" },
]
}
@smartbit4all/form v1.2.4
Type: Update
The label position of the Toggle button can be set.
export enum ToggleLabelPosition {
BEFORE = "before",
AFTER = "after",
}
export interface SmartFormWidget<T> {
...
toggleLabelPosition?: ToggleLabelPosition;
}
@smartbit4all/form v1.2.3
Type: Feature
The following widget types can be set to readonly:
- TEXT_FIELD
- TEXT_FIELD_NUMBER
- TEXT_FIELD_CHIPS
- TEXT_BOX
The change:
export interface SmartFormWidget<T> {
...
isReadonly?: boolean;
}
@smartbit4all/form v1.2.2
Type: Bug fix
Fix row layout inside Container widgets. From now every row item align to center.
@smartbit4all/form v1.2.1
Type: Update
From now on custom buttons can be added to two types of inputs:
TEXT_FIELD
TEXT_FIELD_NUMBER
The properties of the custom button:
export enum SmartFormTextFieldButtonIconPosition {
PRE,
POST,
}
export interface SmartFormTextFieldButton {
icon?: string;
iconPosition?: SmartFormTextFieldButtonIconPosition;
label?: string;
callback: (widget: SmartFormWidget<any>) => any;
color?: ThemePalette;
}
export interface SmartFormWidget<T> {
...
textFieldButton?: SmartFormTextFieldButton;
}
@smartbit4all/form v1.2.0
Type: Update
Slide Toggle has been added as a new SmarFormWidget type.
Changes:
Toggle SmartFormWidgetType
export enum SmartFormWidgetType { TEXT_FIELD, TEXT_FIELD_NUMBER, TEXT_FIELD_CHIPS, TEXT_BOX, SELECT, SELECT_MULTIPLE, CHECK_BOX, CHECK_BOX_TABLE, RADIO_BUTTON, DATE_PICKER, FILE_UPLOAD, ITEM, CONTAINER, LABEL, TIME, >>> TOGGLE }
SmartFormWidgetComponent html
<div *ngSwitchCase="smartFormWidgetType.TOGGLE"> <div *ngIf="widgetInstance.showLabel"> <h4>{{ widgetInstance.label }}</h4> </div> <mat-slide-toggle formControlName="{{ widgetInstance.key }}" value="{{ widgetInstance.value }}" (change)="onValueChange?.next($event)" >{{ widgetInstance.label }}</mat-slide-toggle > </div>
@smartbit4all/form v1.1.11
Type: Update
The name property of the SmartForm
became nullable.
export interface SmartForm {
name?: string;
...
}
@smartbit4all/form v1.1.10
Type: Bugfix
Calling submitForm had not validated the form.
@smartbit4all/form v1.1.7
Type: Bugfix
Fix CSS class issue.
@smartbit4all/form v1.1.5
Type: Update
Fix CSS class in label and for layout classes. Select and Multiple-select widget visible value can be set by SmartFormWidget's label property.
@smartbit4all/form v1.1.4
Type: Feature
Show label can be set globally on form, however it can be overrided on widgets.
@smartbit4all/form v1.1.1
Type: Feature
From now on TextFields can be used as password fields.
@smartbit4all/form v1.1.0
Type: Feature
Feature: custom CSS class for widgets
The SmartFormWidget
got a new property (cssClass?: string;), which allows to inject any custom CSS class for each widgets.
Feature: onBlur and onValueChange
From now on SmartformComponent
has two subscribable Subjects:
- The onBlur subject signals when the user leaves the SmartFormWidget's input field.
- The second subject is the onValueChange which emits an event when the value of the SmartFormWidget was changed.
The onBlur event can be used on the following types of widgets:
- TEXT_FIELD
- TEXT_FIELD_NUMBER
- TEXT_FIELD_CHIPS
- TEXT_BOX
- DATE_PICKER
- SELECT
- SELECT_MULTIPLE
- TIME
The onValuechange event can be used on the following types of widgets:
- RADIO_BUTTON
- CHECK_BOX
- SELECT
- SELECT_MULTIPLE
How to use it:
Firstly, set the useOnBlurEvent and useOnValueChangeEvent properties to true.
this.smartForm = {
name: '',
direction: SmartFormWidgetDirection.COL,
widgets: [ ... ],
useOnBlurEvent: true,
useOnValueChangeEvent: true
};
Secondly, subscribe to the events.
@ViewChild('exampleForm') child?: SmartformComponent;
smartForm: SmartForm;
ngAfterViewInit(){
this.child?.onBlurSubject.subscribe( ... );
this.child?.onValueChangeSubject.subscribe( ... );
}
@smartbit4all/form v1.0.1
Type: Update
The package has been published.
@smartbit4all/form v0.2.0
Type: Feature
From now on SmartForm supports object handling by default. This means that an object with default values can be added to the SmartForm, and if the keys of the SmartFormWidgets are matches with the properties of the given object, the value changes will be handled by the SmartFormService automatically.
Let's see an examplatory scenario:
You have an object like this:
const loginRequestDetails = {
email: "[email protected]",
password: "examplePwd123#"
}
You want to use this in your form:
this.smartForm = {
name: '',
direction: SmartFormWidgetDirection.COL,
model: loginRequestDetails,
widgets: [
{
key: 'email',
label: 'Email',
type: SmartFormWidgetType.TEXT_FIELD,
value: '',
validators: [Validators.required, Validators.email],
errorMessage: 'It is not a valid email.'
},
{
key: 'password',
label: 'Password',
type: SmartFormWidgetType.TEXT_FIELD,
value: '',
validators: [Validators.required],
}
]
};
The output will be this:
Password
After submit:
After you have submitted the SmartForm, the new values are available in this.smartForm.model
.
@smartbit4all/form v0.1.7
Type: Bugfix
A major bug has been fixed which made getting the value of a container impossible.
In the previous version the SmartFormService only had the toSmartForm() function, which was not able to recreate the smartForm in depth.
The bugfix:
toSmartForm(group: FormGroup, smartForm: SmartForm): SmartForm {
smartForm = this.toSmartFormDeeply(smartForm.widgets, group, smartForm);
return smartForm;
}
toSmartFormDeeply(
widgets: SmartFormWidget<any>[],
group: FormGroup,
smartForm: SmartForm
): SmartForm {
widgets.forEach((widget) => {
if (widget.type === SmartFormWidgetType.CONTAINER && widget.valueList?.length) {
smartForm = this.toSmartFormDeeply(widget.valueList, group, smartForm);
} else {
widget.value = group.controls[widget.key].value;
}
});
return smartForm;
}
@smartbit4all/form v0.1.6
Type: Feature
This version contains one major change: TIME picker component have been added. Small layout change: 1em margin have been added to CONTAINER typed widgets.
Usage have not changed.
@smartbit4all/form v0.1.5
Type: Feature
This version contains two changes: LABEL type to the SmartFormWidgetType enum and widgetDescription to the SmartFormWidget have been added.
Changes:
The LABEL type widget can be used as separated label for the input field. Description can be added to the label if you'd like to.
@smartbit4all/form v0.1.4
Type: Feature
This version contains two major changes: a submit function and custom validators have been added to the SmartForm
.
Changes:
The submitForm() function is implemented in the SmartformComponent
. The new values are translated back to the given SmartForm
object if the status of the form is valid. If it is not, the function throws an error with the current state.
submitForm(): SmartForm {
if (this.form.status === "VALID") {
return this.service.toSmartForm(this.form, this.smartForm);
} else {
throw new Error(`The form status is ${this.form.status}.`);
}
}
In order to use multiple custom validators, the SmartFormWidget
got a validators property. A custom error message can be set with the errorMessage property.
export interface SmartFormWidget<T> {
...
validators?: ValidatorFn[];
errorMessage?: string;
}
@smartbit4all/form v0.1.2
Type: Feature
Prefix and Suffix have been added to SmartFormWidget
. These two can be used with TextFields.
TEXT_FIELD_NUMBER as a new SmartFormWidgetType
can be used for numbers.
Example for prefix, suffix and TEXT_FIELD_NUMBER:
{
key: 'money',
label: 'Money',
type: SmartFormWidgetType.TEXT_FIELD_NUMBER,
value: 10,
prefix: '€',
suffix: '.00',
...
}
Output: € 10.00
@smartbit4all/form v0.1.1
Type: Feature
CONTAINER
has been added to SmartFormWidgetType
.
This CONTAINER type can be used for creating inline forms with n widgets in it.
CONTAINER usage example
{
key: 'container-key',
label: '',
value: '',
type: SmartFormWidgetType.CONTAINER,
direction: SmartFormWidgetDirection.ROW,
valueList: [
{
key: 'container-key-1',
label: '1st label',
type: SmartFormWidgetType.TEXT_FIELD,
value: this.containerValue,
...
},
{
key: 'container-key-2',
label: '2nd label',
type: SmartFormWidgetType.TEXT_FIELD,
value: this.containerValue,
...
},
...
],
...
}
Type: Feature
A new property has been added to SmartFormWidget
which disables the SmartFormWidget.
The new property
export interface SmartFormWidget<T> {
...
isDisabled?: boolean;
}
The change in the SmartFormService
createFormControls(widgets: SmartFormWidget<any>[]) {
...
if (widget.isDisabled) {
formControl.disable();
}
...
}
Type: Bugfix
The CHECKBOX widget had a bug, which caused that the label was shown after the options.
The code snippet which caused the bug
.checkbox {
flex-direction: column-reverse;
}
The code snippet which solved the bug
.checkbox {
flex-direction: column;
}
@smartbit4all/form v0.0.2
Type: Feature
The basic smart form with its features.