diff --git a/.eslintrc.json b/.eslintrc.json index ce76e5ef5..9a477f1b9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -139,13 +139,10 @@ "plugin:prettier/recommended" ], "rules": { - "@angular-eslint/template/button-has-type": "off", "@angular-eslint/template/click-events-have-key-events": "off", "@angular-eslint/template/cyclomatic-complexity": "off", "@angular-eslint/template/i18n": "off", "@angular-eslint/template/interactive-supports-focus": "off", - "@angular-eslint/template/prefer-control-flow": "off", - "@angular-eslint/template/use-track-by-function": "off", "prettier/prettier": [ "error", { diff --git a/.npmrc b/.npmrc index dc34a6fa2..c83fbeb3a 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1 @@ -@dynamic-forms:registry=https://registry.npmjs.org - -legacy-peer-deps=true \ No newline at end of file +@dynamic-forms:registry=https://registry.npmjs.org \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 04a112b33..2f5b61178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## 18.1.0 (2024-09-28) + +* Release without any notable changes in comparison to 18.1.0-rc.0 + +## 18.1.0-rc.0 (2024-09-28) + +* Release without any notable changes in comparison to 18.1.0-next.0 + +## 18.1.0-next.0 (2024-09-26) + +### Features + +* **core:** use control flow +* **core:** support of input mask converters (number and datetime) +* **bootstrap:** use control flow +* **bootstrap:** use input mask converters for number and datetime +* **material:** use control flow +* **material:** use input mask converters for number and datetime +* **markdown:** update to [marked](https://github.com/markedjs/marked) 14 + ## 18.0.0 (2024-05-29) * Release without any notable changes in comparison to release candidate 18.0.0-rc.0 diff --git a/README.md b/README.md index 83c7ed89f..ce1d11351 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,12 @@ This is an [**Angular**](https://angular.dev) project for dynamic forms based on ## **Packages** -### **Version 18** [![Build Status](https://dev.azure.com/alexandergebuhr/dynamic-forms/_apis/build/status/dynamic-forms-publish?branchName=refs/tags/18.0.0)](https://dev.azure.com/alexandergebuhr/dynamic-forms/_build/latest?definitionId=45&branchName=refs/tags/18.0.0) +### **Version 18** [![Build Status](https://dev.azure.com/alexandergebuhr/dynamic-forms/_apis/build/status/dynamic-forms-publish?branchName=refs/tags/18.1.0)](https://dev.azure.com/alexandergebuhr/dynamic-forms/_build/latest?definitionId=45&branchName=refs/tags/18.1.0) -- `npm install @dynamic-forms/core@18.0.0` -- `npm install @dynamic-forms/bootstrap@18.0.0` -- `npm install @dynamic-forms/material@18.0.0` -- `npm install @dynamic-forms/markdown@18.0.0` +- `npm install @dynamic-forms/core@18.1.0` +- `npm install @dynamic-forms/bootstrap@18.1.0` +- `npm install @dynamic-forms/material@18.1.0` +- `npm install @dynamic-forms/markdown@18.1.0` ### **Version 17** [![Build Status](https://dev.azure.com/alexandergebuhr/dynamic-forms/_apis/build/status/dynamic-forms-publish?branchName=refs/tags/17.0.0)](https://dev.azure.com/alexandergebuhr/dynamic-forms/_build/latest?definitionId=45&branchName=refs/tags/17.0.0) @@ -102,7 +102,7 @@ This is an [**Angular**](https://angular.dev) project for dynamic forms based on ## **Demos** -### **Version 18** [![Build Status](https://dev.azure.com/alexandergebuhr/dynamic-forms/_apis/build/status/dynamic-forms-cd?branchName=18.0.x)](https://dev.azure.com/alexandergebuhr/dynamic-forms/_build/latest?definitionId=43&branchName=18.0.x) +### **Version 18** [![Build Status](https://dev.azure.com/alexandergebuhr/dynamic-forms/_apis/build/status/dynamic-forms-cd?branchName=18.1.x)](https://dev.azure.com/alexandergebuhr/dynamic-forms/_build/latest?definitionId=43&branchName=18.1.x) - Built with [Angular 18](https://v18.angular.dev/) - Environments include [DEV](https://dynamic-forms.azurewebsites.net/v18/dev/) and [PROD](https://dynamic-forms.azurewebsites.net/v18/) diff --git a/apps/demo-e2e/src/editor/editor.e2e-spec.ts b/apps/demo-e2e/src/editor/editor.e2e-spec.ts new file mode 100644 index 000000000..739cfe181 --- /dev/null +++ b/apps/demo-e2e/src/editor/editor.e2e-spec.ts @@ -0,0 +1,22 @@ +import { EditorPage } from './editor.po'; + +describe('dynamic-forms demo editor', () => { + const themes = ['bootstrap', 'material']; + + themes.forEach(theme => { + describe(`for theme ${theme}`, () => { + let page: EditorPage; + + beforeEach(() => { + page = new EditorPage(theme); + }); + + it('has url and title', async () => { + await page.navigateTo(); + + expect(await page.getUrl()).toContain(`/editor/${theme}`); + expect(await page.getTitle()).toEqual('dynamic-forms'); + }); + }); + }); +}); diff --git a/apps/demo-e2e/src/editor/editor.po.ts b/apps/demo-e2e/src/editor/editor.po.ts new file mode 100644 index 000000000..9a68799fa --- /dev/null +++ b/apps/demo-e2e/src/editor/editor.po.ts @@ -0,0 +1,7 @@ +import { Page } from '../page-base'; + +export class EditorPage extends Page { + constructor(public theme: string) { + super(`/editor/${theme}`); + } +} diff --git a/apps/demo/src/app/app-state.module.ts b/apps/demo/src/app/app-state.module.ts deleted file mode 100644 index d3a75630b..000000000 --- a/apps/demo/src/app/app-state.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { NgModule } from '@angular/core'; -import { NgxsStoragePluginModule } from '@ngxs/storage-plugin'; -import { NgxsModule } from '@ngxs/store'; -import { environment } from './../environments/environment'; -import { ConfigState } from './state/config/config.state'; -import { ExamplesState } from './state/examples/examples.state'; -import { LayoutState } from './state/layout/layout.state'; -import { NotificationsState } from './state/notifications/notifications.state'; -import { PreferencesState } from './state/preferences/preferences.state'; -import { ProgressState } from './state/progress/progress.state'; - -@NgModule({ - imports: [ - NgxsModule.forRoot([ConfigState, ExamplesState, LayoutState, NotificationsState, PreferencesState, ProgressState], { - developmentMode: !environment.production, - }), - NgxsStoragePluginModule.forRoot({ - key: [PreferencesState], - }), - ], -}) -export class AppStateModule {} diff --git a/apps/demo/src/app/app-states.ts b/apps/demo/src/app/app-states.ts new file mode 100644 index 000000000..4f7b377d9 --- /dev/null +++ b/apps/demo/src/app/app-states.ts @@ -0,0 +1,21 @@ +import { withNgxsStoragePlugin } from '@ngxs/storage-plugin'; +import { NgxsModuleOptions } from '@ngxs/store'; +import { environment } from '../environments/environment'; +import { ConfigState } from './state/config/config.state'; +import { ExamplesState } from './state/examples/examples.state'; +import { LayoutState } from './state/layout/layout.state'; +import { NotificationsState } from './state/notifications/notifications.state'; +import { PreferencesState } from './state/preferences/preferences.state'; +import { ProgressState } from './state/progress/progress.state'; + +export const appStates = [ConfigState, ExamplesState, LayoutState, NotificationsState, PreferencesState, ProgressState]; + +export const appStateOptions: NgxsModuleOptions = { + developmentMode: !environment.production, +}; + +export const appStateFeatures = [ + withNgxsStoragePlugin({ + keys: [PreferencesState], + }), +]; diff --git a/apps/demo/src/app/editor/form-editor-logs.component.html b/apps/demo/src/app/editor/form-editor-logs.component.html index 369bbf00d..df4fb3c8a 100644 --- a/apps/demo/src/app/editor/form-editor-logs.component.html +++ b/apps/demo/src/app/editor/form-editor-logs.component.html @@ -18,7 +18,7 @@ - diff --git a/apps/demo/src/app/form/bootstrap/bootstrap-form.module.ts b/apps/demo/src/app/form/bootstrap/bootstrap-form.module.ts index bc32e96e0..caee4a471 100644 --- a/apps/demo/src/app/form/bootstrap/bootstrap-form.module.ts +++ b/apps/demo/src/app/form/bootstrap/bootstrap-form.module.ts @@ -1,6 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { provideBsDynamicFormsWithDefaultFeatures } from '@dynamic-forms/bootstrap'; -import { withBsDynamicFormInputMask } from '@dynamic-forms/bootstrap/input-mask'; +import { withBsDynamicFormInputMask, withBsDynamicFormInputMaskConverters } from '@dynamic-forms/bootstrap/input-mask'; import { withDynamicFormColors, withDynamicFormControlValidatorFactory, withDynamicFormIcons } from '@dynamic-forms/core'; import { withDynamicFormsMarkdownFeatures } from '@dynamic-forms/markdown'; import { v4 } from 'uuid'; @@ -41,6 +41,7 @@ const features = [ withDynamicFormIcons(icons), withDynamicFormColors(colors), withBsDynamicFormInputMask(), + withBsDynamicFormInputMaskConverters(), withDynamicFormControlValidatorFactory(dynamicFormControlUniqueUsernameValidatorTypeFactory, [HttpClient]), ...withDynamicFormsMarkdownFeatures(), ]; diff --git a/apps/demo/src/app/form/form-submit-dialog.component.html b/apps/demo/src/app/form/form-submit-dialog.component.html index 5cb68d355..8f8b8645a 100644 --- a/apps/demo/src/app/form/form-submit-dialog.component.html +++ b/apps/demo/src/app/form/form-submit-dialog.component.html @@ -18,5 +18,5 @@
- +
diff --git a/apps/demo/src/app/form/material/material-form.module.ts b/apps/demo/src/app/form/material/material-form.module.ts index 82f3e0365..940a3a847 100644 --- a/apps/demo/src/app/form/material/material-form.module.ts +++ b/apps/demo/src/app/form/material/material-form.module.ts @@ -2,8 +2,8 @@ import { HttpClient } from '@angular/common/http'; import { provideNativeDateAdapter } from '@angular/material/core'; import { withDynamicFormColors, withDynamicFormControlValidatorFactory, withDynamicFormIcons } from '@dynamic-forms/core'; import { withDynamicFormsMarkdownFeatures } from '@dynamic-forms/markdown'; -import { provideMatDynamicFormsWithDefaultFeatures } from '@dynamic-forms/material'; -import { withMatDynamicFormInputMask } from '@dynamic-forms/material/input-mask'; +import { provideMatDynamicFormsWithDefaultFeatures, provideNativeDatetimeAdapter } from '@dynamic-forms/material'; +import { withMatDynamicFormInputMask, withMatDynamicFormInputMaskConverters } from '@dynamic-forms/material/input-mask'; import { v4 } from 'uuid'; import { dynamicFormControlUniqueUsernameValidatorTypeFactory } from '../dynamic-form-extensions'; @@ -46,9 +46,14 @@ const features = [ withDynamicFormColors(colors), withDynamicFormControlValidatorFactory(dynamicFormControlUniqueUsernameValidatorTypeFactory, [HttpClient]), withMatDynamicFormInputMask(), + withMatDynamicFormInputMaskConverters(), ...withDynamicFormsMarkdownFeatures(), ]; export function provideMaterialForm() { - return [...provideMatDynamicFormsWithDefaultFeatures(config, ...features), ...provideNativeDateAdapter()]; + return [ + ...provideMatDynamicFormsWithDefaultFeatures(config, ...features), + ...provideNativeDateAdapter(), + ...provideNativeDatetimeAdapter(), + ]; } diff --git a/apps/demo/src/app/layout/content/sidebar/sidebar-menu/sidebar-menu.component.html b/apps/demo/src/app/layout/content/sidebar/sidebar-menu/sidebar-menu.component.html index 0a4ffd7dd..2c15068d0 100644 --- a/apps/demo/src/app/layout/content/sidebar/sidebar-menu/sidebar-menu.component.html +++ b/apps/demo/src/app/layout/content/sidebar/sidebar-menu/sidebar-menu.component.html @@ -1,7 +1,7 @@ @if (treeDataSource$ | async; as treeDataSource) { - +
  • @if (menuItem.route) { {{ @@ -13,9 +13,9 @@ }
  • - +
  • - diff --git a/apps/demo/src/app/layout/header/docs-menu/docs-menu.component.html b/apps/demo/src/app/layout/header/docs-menu/docs-menu.component.html index 4aaf8a0a3..9c0a533a6 100644 --- a/apps/demo/src/app/layout/header/docs-menu/docs-menu.component.html +++ b/apps/demo/src/app/layout/header/docs-menu/docs-menu.component.html @@ -1,5 +1,5 @@ @if (repository$ | async; as repository) { - diff --git a/apps/demo/src/app/layout/header/editor-menu/editor-menu-panel.component.html b/apps/demo/src/app/layout/header/editor-menu/editor-menu-panel.component.html index 494f1e445..c7f420db4 100644 --- a/apps/demo/src/app/layout/header/editor-menu/editor-menu-panel.component.html +++ b/apps/demo/src/app/layout/header/editor-menu/editor-menu-panel.component.html @@ -4,7 +4,7 @@ } @for (item of items; track $index) { @if (item.items) { - + } @if (item.id) { diff --git a/apps/demo/src/app/layout/header/editor-menu/editor-menu.component.html b/apps/demo/src/app/layout/header/editor-menu/editor-menu.component.html index ca14fb067..f5df58880 100644 --- a/apps/demo/src/app/layout/header/editor-menu/editor-menu.component.html +++ b/apps/demo/src/app/layout/header/editor-menu/editor-menu.component.html @@ -1,11 +1,11 @@ @if ((items$ | async) || []; as items) { - - - + + diff --git a/apps/demo/src/app/layout/header/examples-menu/examples-menu-panel.component.html b/apps/demo/src/app/layout/header/examples-menu/examples-menu-panel.component.html index 13ad412fb..1bdba7575 100644 --- a/apps/demo/src/app/layout/header/examples-menu/examples-menu-panel.component.html +++ b/apps/demo/src/app/layout/header/examples-menu/examples-menu-panel.component.html @@ -1,7 +1,7 @@ @for (item of items; track $index) { @if (item.items) { - + } @if (item.id) { diff --git a/apps/demo/src/app/layout/header/examples-menu/examples-menu.component.html b/apps/demo/src/app/layout/header/examples-menu/examples-menu.component.html index bdbc8e07a..2a7c1b93f 100644 --- a/apps/demo/src/app/layout/header/examples-menu/examples-menu.component.html +++ b/apps/demo/src/app/layout/header/examples-menu/examples-menu.component.html @@ -1,11 +1,11 @@ @if (items$ | async; as items) { - - - + + diff --git a/apps/demo/src/app/layout/header/notifications-toggle/notifications-toggle.component.html b/apps/demo/src/app/layout/header/notifications-toggle/notifications-toggle.component.html index 221e0e4da..ac7d218b8 100644 --- a/apps/demo/src/app/layout/header/notifications-toggle/notifications-toggle.component.html +++ b/apps/demo/src/app/layout/header/notifications-toggle/notifications-toggle.component.html @@ -1,4 +1,4 @@ - diff --git a/apps/demo/src/app/layout/header/preferences-menu/preferences-menu.component.ts b/apps/demo/src/app/layout/header/preferences-menu/preferences-menu.component.ts index 8cdeccd3f..3fe86888d 100644 --- a/apps/demo/src/app/layout/header/preferences-menu/preferences-menu.component.ts +++ b/apps/demo/src/app/layout/header/preferences-menu/preferences-menu.component.ts @@ -29,7 +29,7 @@ export class PreferencesMenuComponent { dynamicForm: MaterialFormComponent; constructor(private store: Store) { - this.model$ = this.store.select(PreferencesState).pipe( + this.model$ = this.store.select(PreferencesState.preferences).pipe( filter(preferences => preferences !== this.dynamicForm?.form?.value), map((preferences: Preferences) => { if (preferences) { diff --git a/apps/demo/src/app/layout/header/sidebar-toggle/sidebar-toggle.component.html b/apps/demo/src/app/layout/header/sidebar-toggle/sidebar-toggle.component.html index 1f612d63f..429217ccd 100644 --- a/apps/demo/src/app/layout/header/sidebar-toggle/sidebar-toggle.component.html +++ b/apps/demo/src/app/layout/header/sidebar-toggle/sidebar-toggle.component.html @@ -1,3 +1,3 @@ - diff --git a/apps/demo/src/app/layout/header/versions-menu/versions-menu.component.html b/apps/demo/src/app/layout/header/versions-menu/versions-menu.component.html index 313d2dac5..540d02db2 100644 --- a/apps/demo/src/app/layout/header/versions-menu/versions-menu.component.html +++ b/apps/demo/src/app/layout/header/versions-menu/versions-menu.component.html @@ -1,6 +1,6 @@ @if (versions$ | async; as versions) { @if (versions.length) { - diff --git a/apps/demo/src/app/monaco/monaco-editor.component.html b/apps/demo/src/app/monaco/monaco-editor.component.html index e677976f4..5baec8655 100644 --- a/apps/demo/src/app/monaco/monaco-editor.component.html +++ b/apps/demo/src/app/monaco/monaco-editor.component.html @@ -1,12 +1,12 @@
    - + - - diff --git a/apps/demo/src/app/state/preferences/preferences.state.ts b/apps/demo/src/app/state/preferences/preferences.state.ts index 7da3bbcce..e01bdf810 100644 --- a/apps/demo/src/app/state/preferences/preferences.state.ts +++ b/apps/demo/src/app/state/preferences/preferences.state.ts @@ -9,6 +9,11 @@ import { FormEditorPreferences, PREFERENCES, Preferences, ThemePreferences, defa }) @Injectable() export class PreferencesState { + @Selector() + static preferences(state: Preferences): Preferences { + return state; + } + @Selector() static theme(state: Preferences): ThemePreferences { return state?.theme; diff --git a/apps/demo/src/assets/config.json b/apps/demo/src/assets/config.json index 0be42a7ee..17f8aba2c 100644 --- a/apps/demo/src/assets/config.json +++ b/apps/demo/src/assets/config.json @@ -1,5 +1,5 @@ { - "version": "18.0.0", + "version": "18.1.0", "build": "187", "buildUrl": "https://dev.azure.com/alexandergebuhr/dynamic-forms/_build?definitionId=39&_a=summary", "release": "17", @@ -9,14 +9,14 @@ }, "repository": { "url": "https://github.com/dynamic-forms/dynamic-forms", - "branch": "18.0.x", + "branch": "18.1.x", "branchPath": "tree/{{branch}}", "libraryPath": "libs/{{library}}", "commit": null }, "versions": [ { - "name": "18.0.0", + "name": "18.1.0", "url": "https://dynamic-forms.azurewebsites.net/v18/dev" }, { diff --git a/apps/demo/src/assets/config.prod.json b/apps/demo/src/assets/config.prod.json index cd722e53b..3bb18e01b 100644 --- a/apps/demo/src/assets/config.prod.json +++ b/apps/demo/src/assets/config.prod.json @@ -1,5 +1,5 @@ { - "version": "18.0.0", + "version": "18.1.0", "build": "187", "buildUrl": "https://dev.azure.com/alexandergebuhr/dynamic-forms/_build?definitionId=39&_a=summary", "release": "17", @@ -9,14 +9,14 @@ }, "repository": { "url": "https://github.com/dynamic-forms/dynamic-forms", - "branch": "18.0.x", + "branch": "18.1.x", "branchPath": "tree/{{branch}}", "libraryPath": "libs/{{library}}", "commit": null }, "versions": [ { - "name": "18.0.0", + "name": "18.1.0", "url": "https://dynamic-forms.azurewebsites.net/v18" }, { diff --git a/apps/demo/src/assets/examples-menu.json b/apps/demo/src/assets/examples-menu.json index 611f00288..4edfa6d5d 100644 --- a/apps/demo/src/assets/examples-menu.json +++ b/apps/demo/src/assets/examples-menu.json @@ -74,12 +74,30 @@ "label": "Checkbox" }, { - "id": "inputs-variations-file", - "label": "File" + "groupId": "input-mask", + "label": "Input Mask", + "items": [ + { + "id": "inputs-variations-input-mask", + "label": "Plain" + }, + { + "id": "inputs-variations-input-mask-default-value", + "label": "Default value" + }, + { + "id": "inputs-variations-input-mask-converter", + "label": "Converter" + }, + { + "id": "inputs-variations-input-mask-converter-default-value", + "label": "Converter and default value" + } + ] }, { - "id": "inputs-variations-input-mask", - "label": "Input Mask" + "id": "inputs-variations-file", + "label": "File" }, { "id": "inputs-variations-select", diff --git a/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter-default-value.json b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter-default-value.json new file mode 100644 index 000000000..a86f527d6 --- /dev/null +++ b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter-default-value.json @@ -0,0 +1,207 @@ +{ + "template": { + "label": "Input mask variations" + }, + "children": [ + { + "key": "format", + "type": "control", + "template": { + "label": "Format", + "input": { + "type": "select", + "options": [ + { + "label": "United States", + "value": "us" + }, + { + "label": "United Kingdom", + "value": "uk" + }, + { + "label": "Germany", + "value": "de" + } + ], + "defaultValue": "de" + } + } + }, + { + "type": "content", + "template": { + "content": "

    Numeric input masks with converter

    " + } + }, + { + "key": "rightAlign", + "type": "control", + "template": { + "label": "Right align", + "input": { + "type": "checkbox", + "defaultValue": false + } + } + }, + { + "key": "decimal", + "type": "control", + "template": { + "label": "Decimal", + "input": { + "type": "input-mask", + "placeholder": "Enter a decimal number", + "defaultValue": 1.25, + "maskOptions": { + "alias": "decimal", + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "integer", + "type": "control", + "template": { + "label": "Integer", + "input": { + "type": "input-mask", + "placeholder": "Enter an integer", + "defaultValue": 1, + "maskOptions": { + "alias": "integer", + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "percentage", + "type": "control", + "template": { + "label": "Percentage", + "input": { + "type": "input-mask", + "placeholder": "Enter a percentage value", + "defaultValue": 12.5, + "maskOptions": { + "alias": "percentage", + "digits": 1, + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "currency", + "type": "control", + "template": { + "label": "Currency", + "input": { + "type": "input-mask", + "placeholder": "Enter an amount", + "defaultValue": 10000, + "maskOptions": { + "alias": "currency", + "useConverter": true, + "prefix": "USD " + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.groupSeparator": "data.root.model.format === 'de' ? '.' : ','", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "type": "content", + "template": { + "content": "

    Datetime input masks with converter

    " + } + }, + { + "key": "datetime", + "type": "control", + "template": { + "label": "Datetime", + "input": { + "type": "input-mask", + "placeholder": "Enter a date time", + "defaultValue": "2020-01-01T12:00Z", + "maskOptions": { + "alias": "datetime", + "useConverter": true, + "inputFormat": "dd/mm/yyyy HH:MM" + } + } + }, + "expressions": { + "input.maskOptions.inputFormat": "data.root.model.format === 'de' ? 'dd.mm.yyyy HH:MM' : data.root.model.format === 'uk' ? 'dd/mm/yyyy HH:MM' : 'yyyy-mm-dd HH:MM'" + } + }, + { + "key": "date", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a date", + "defaultValue": "2020-01-01", + "maskOptions": { + "alias": "datetime", + "useConverter": true, + "inputFormat": "dd/mm/yyyy" + } + } + }, + "expressions": { + "input.maskOptions.inputFormat": "data.root.model.format === 'de' ? 'dd.mm.yyyy' : data.root.model.format === 'uk' ? 'dd/mm/yyyy' : 'yyyy-mm-dd'" + } + } + ], + "footerActions": [ + { + "id": "action-submit", + "type": "button", + "template": { + "type": "submit", + "label": "Submit" + }, + "expressions": { + "disabled": "data.root.status !== 'VALID'" + } + }, + { + "id": "action-reset", + "type": "button", + "template": { + "type": "reset", + "label": "Reset" + } + }, + { + "id": "action-reset-default", + "type": "button", + "template": { + "type": "button", + "label": "Reset default", + "action": "resetDefault" + } + } + ] +} \ No newline at end of file diff --git a/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter.json b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter.json new file mode 100644 index 000000000..011915fa8 --- /dev/null +++ b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-converter.json @@ -0,0 +1,192 @@ +{ + "template": { + "label": "Input mask variations" + }, + "children": [ + { + "key": "format", + "type": "control", + "template": { + "label": "Format", + "input": { + "type": "select", + "options": [ + { + "label": "United States", + "value": "us" + }, + { + "label": "United Kingdom", + "value": "uk" + }, + { + "label": "Germany", + "value": "de" + } + ], + "defaultValue": "us" + } + } + }, + { + "type": "content", + "template": { + "content": "

    Numeric input masks with converter

    " + } + }, + { + "key": "rightAlign", + "type": "control", + "template": { + "label": "Right align", + "input": { + "type": "checkbox", + "defaultValue": false + } + } + }, + { + "key": "decimal", + "type": "control", + "template": { + "label": "Decimal", + "input": { + "type": "input-mask", + "placeholder": "Enter a decimal number", + "maskOptions": { + "alias": "decimal", + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "integer", + "type": "control", + "template": { + "label": "Integer", + "input": { + "type": "input-mask", + "placeholder": "Enter an integer", + "maskOptions": { + "alias": "integer", + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "percentage", + "type": "control", + "template": { + "label": "Percentage", + "input": { + "type": "input-mask", + "placeholder": "Enter a percentage value", + "maskOptions": { + "alias": "percentage", + "digits": 1, + "useConverter": true + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "currency", + "type": "control", + "template": { + "label": "Currency", + "input": { + "type": "input-mask", + "placeholder": "Enter an amount", + "maskOptions": { + "alias": "currency", + "useConverter": true, + "prefix": "USD " + } + } + }, + "expressions": { + "input.maskOptions.radixPoint": "data.root.model.format === 'de' ? ',' : '.'", + "input.maskOptions.groupSeparator": "data.root.model.format === 'de' ? '.' : ','", + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "type": "content", + "template": { + "content": "

    Datetime input masks with converter

    " + } + }, + { + "key": "datetime", + "type": "control", + "template": { + "label": "Datetime", + "input": { + "type": "input-mask", + "placeholder": "Enter a date time", + "maskOptions": { + "alias": "datetime", + "useConverter": true, + "inputFormat": "dd/mm/yyyy HH:MM" + } + } + }, + "expressions": { + "input.maskOptions.inputFormat": "data.root.model.format === 'de' ? 'dd.mm.yyyy HH:MM' : data.root.model.format === 'uk' ? 'dd/mm/yyyy HH:MM' : 'yyyy-mm-dd HH:MM'" + } + }, + { + "key": "date", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a date", + "maskOptions": { + "alias": "datetime", + "useConverter": true, + "inputFormat": "dd/mm/yyyy" + } + } + }, + "expressions": { + "input.maskOptions.inputFormat": "data.root.model.format === 'de' ? 'dd.mm.yyyy' : data.root.model.format === 'uk' ? 'dd/mm/yyyy' : 'yyyy-mm-dd'" + } + } + ], + "footerActions": [ + { + "id": "action-submit", + "type": "button", + "template": { + "type": "submit", + "label": "Submit" + }, + "expressions": { + "disabled": "data.root.status !== 'VALID'" + } + }, + { + "id": "action-reset", + "type": "button", + "template": { + "type": "reset", + "label": "Reset" + } + } + ] +} \ No newline at end of file diff --git a/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-default-value.json b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-default-value.json new file mode 100644 index 000000000..af61a5963 --- /dev/null +++ b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask-default-value.json @@ -0,0 +1,271 @@ +{ + "template": { + "label": "Input mask variations" + }, + "children": [ + { + "key": "email", + "type": "control", + "template": { + "label": "Email", + "input": { + "type": "input-mask", + "placeholder": "Enter an email", + "defaultValue": "user@mail.com", + "maskOptions": { + "alias": "email" + } + } + } + }, + { + "key": "ip", + "type": "control", + "template": { + "label": "IP", + "input": { + "type": "input-mask", + "placeholder": "Enter an IP address", + "defaultValue": "192.0.0.0", + "maskOptions": { + "alias": "ip" + } + } + } + }, + { + "key": "mac", + "type": "control", + "template": { + "label": "MAC", + "input": { + "type": "input-mask", + "placeholder": "Enter a MAC address", + "defaultValue": "00:00:00:00:00:00", + "maskOptions": { + "alias": "mac" + } + } + } + }, + { + "key": "ssn", + "type": "control", + "template": { + "label": "Social security number", + "input": { + "type": "input-mask", + "placeholder": "Enter a social security number", + "defaultValue": "123-45-6789", + "maskOptions": { + "alias": "ssn" + } + } + } + }, + { + "key": "url", + "type": "control", + "template": { + "label": "URL", + "input": { + "type": "input-mask", + "placeholder": "Enter an URL", + "defaultValue": "dynamic-forms.azurewebsites.net/", + "maskOptions": { + "alias": "url" + } + } + } + }, + { + "key": "vin", + "type": "control", + "template": { + "label": "Vehicle identification number", + "input": { + "type": "input-mask", + "placeholder": "Enter a vehicle identification number", + "defaultValue": "WVWZZZ1JZ3W386752", + "maskOptions": { + "alias": "vin" + } + } + } + }, + { + "type": "content", + "template": { + "content": "

    Numeric input masks

    " + } + }, + { + "key": "rightAlign", + "type": "control", + "template": { + "label": "Right align", + "input": { + "type": "checkbox", + "defaultValue": false + } + } + }, + { + "key": "decimal", + "type": "control", + "template": { + "label": "Decimal", + "input": { + "type": "input-mask", + "placeholder": "Enter a decimal number", + "defaultValue": "1.25", + "maskOptions": { + "alias": "decimal" + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "integer", + "type": "control", + "template": { + "label": "Integer", + "input": { + "type": "input-mask", + "placeholder": "Enter an integer", + "defaultValue": "1", + "maskOptions": { + "alias": "integer" + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "percentage", + "type": "control", + "template": { + "label": "Percentage", + "input": { + "type": "input-mask", + "placeholder": "Enter a percentage value", + "defaultValue": "12.5 %", + "maskOptions": { + "alias": "percentage" + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "key": "currency", + "type": "control", + "template": { + "label": "Currency", + "input": { + "type": "input-mask", + "placeholder": "Enter an amount", + "defaultValue": "USD 10000", + "maskOptions": { + "alias": "currency", + "prefix": "USD " + } + } + }, + "expressions": { + "input.maskOptions.rightAlign": "data.root.model.rightAlign" + } + }, + { + "type": "content", + "template": { + "content": "

    Datetime input masks

    " + } + }, + { + "key": "datetime", + "type": "control", + "template": { + "label": "Datetime", + "input": { + "type": "input-mask", + "placeholder": "Enter a date time", + "defaultValue": "01/01/2020 12:00", + "maskOptions": { + "alias": "datetime", + "inputFormat": "dd/mm/yyyy HH:MM" + } + } + } + }, + { + "key": "date", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a date", + "defaultValue": "01/01/2020", + "maskOptions": { + "alias": "datetime", + "inputFormat": "dd/mm/yyyy" + } + } + } + }, + { + "key": "time", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a time", + "defaultValue": "12:00", + "maskOptions": { + "alias": "datetime", + "inputFormat": "HH:MM" + } + } + } + } + ], + "footerActions": [ + { + "id": "action-submit", + "type": "button", + "template": { + "type": "submit", + "label": "Submit" + }, + "expressions": { + "disabled": "data.root.status !== 'VALID'" + } + }, + { + "id": "action-reset", + "type": "button", + "template": { + "type": "reset", + "label": "Reset" + } + }, + { + "id": "action-reset-default", + "type": "button", + "template": { + "type": "button", + "label": "Reset default", + "action": "resetDefault" + } + } + ] +} \ No newline at end of file diff --git a/apps/demo/src/assets/examples/inputs/variations/inputs-variations-input-mask.json b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask.json similarity index 78% rename from apps/demo/src/assets/examples/inputs/variations/inputs-variations-input-mask.json rename to apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask.json index 4a1a5c50c..cafea2dd4 100644 --- a/apps/demo/src/assets/examples/inputs/variations/inputs-variations-input-mask.json +++ b/apps/demo/src/assets/examples/inputs/variations/input-mask/inputs-variations-input-mask.json @@ -162,7 +162,7 @@ "label": "Currency", "input": { "type": "input-mask", - "placeholder": "Enter a percentage value", + "placeholder": "Enter an amount", "maskOptions": { "alias": "currency", "prefix": "USD " @@ -172,6 +172,57 @@ "expressions": { "input.maskOptions.rightAlign": "data.root.model.rightAlign" } + }, + { + "type": "content", + "template": { + "content": "

    Datetime input masks

    " + } + }, + { + "key": "datetime", + "type": "control", + "template": { + "label": "Datetime", + "input": { + "type": "input-mask", + "placeholder": "Enter a date time", + "maskOptions": { + "alias": "datetime", + "inputFormat": "dd/mm/yyyy HH:MM" + } + } + } + }, + { + "key": "date", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a date", + "maskOptions": { + "alias": "datetime", + "inputFormat": "dd/mm/yyyy" + } + } + } + }, + { + "key": "time", + "type": "control", + "template": { + "label": "Date", + "input": { + "type": "input-mask", + "placeholder": "Enter a time", + "maskOptions": { + "alias": "datetime", + "inputFormat": "HH:MM" + } + } + } } ], "footerActions": [ diff --git a/apps/demo/src/main.ts b/apps/demo/src/main.ts index 8d5a2666a..473372616 100644 --- a/apps/demo/src/main.ts +++ b/apps/demo/src/main.ts @@ -1,9 +1,10 @@ import { HTTP_INTERCEPTORS, provideHttpClient } from '@angular/common/http'; -import { APP_INITIALIZER, enableProdMode, importProvidersFrom } from '@angular/core'; +import { APP_INITIALIZER, enableProdMode } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { provideAnimations } from '@angular/platform-browser/animations'; import { provideRouter, withComponentInputBinding } from '@angular/router'; -import { AppStateModule } from './app/app-state.module'; +import { provideStore } from '@ngxs/store'; +import { appStateFeatures, appStateOptions, appStates } from './app/app-states'; import { AppComponent } from './app/app.component'; import { appRoutes } from './app/app.routes'; import { AppService, appInitializer } from './app/app.service'; @@ -19,7 +20,7 @@ bootstrapApplication(AppComponent, { provideAnimations(), provideHttpClient(), provideRouter(appRoutes, withComponentInputBinding()), - importProvidersFrom(AppStateModule), + provideStore(appStates, appStateOptions, ...appStateFeatures), { provide: APP_INITIALIZER, useFactory: appInitializer, diff --git a/apps/demo/src/styles.scss b/apps/demo/src/styles.scss index 6705a4594..926fe6c75 100644 --- a/apps/demo/src/styles.scss +++ b/apps/demo/src/styles.scss @@ -59,24 +59,24 @@ html, body { } body { + --app-primary-color: #{mat.get-theme-color($app-light-theme, primary)}; + --app-primary-background: #{mat.get-theme-color($app-light-theme, primary-container)}; + margin: 0; @include mat.all-component-themes($app-light-theme); - --app-primary-color: #{mat.get-theme-color($app-light-theme, primary)}; - --app-primary-background: #{mat.get-theme-color($app-light-theme, primary-container)}; - .button-content { display: flex; align-items: center; } &.dark-mode { - @include mat.all-component-colors($app-dark-theme); - --app-primary-color: #{mat.get-theme-color($app-dark-theme, primary)}; --app-primary-background: #{mat.get-theme-color($app-dark-theme, primary-container)}; + @include mat.all-component-colors($app-dark-theme); + .dynamic-form-markdown { code, pre { background-color: #696969; diff --git a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask-converter.ts b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask-converter.ts new file mode 100644 index 000000000..fa333a468 --- /dev/null +++ b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask-converter.ts @@ -0,0 +1,6 @@ +import { DynamicFormsFeature } from '@dynamic-forms/core'; +import { withDynamicFormInputMaskDefaultConverters } from '@dynamic-forms/core/input-mask'; + +export function withBsDynamicFormInputMaskConverters(): DynamicFormsFeature { + return withDynamicFormInputMaskDefaultConverters(); +} diff --git a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.component.spec.ts b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.component.spec.ts index 4d86fc14c..42f59f073 100644 --- a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.component.spec.ts +++ b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.component.spec.ts @@ -10,7 +10,11 @@ import { DynamicFormLibraryService, DynamicFormValidationService, } from '@dynamic-forms/core'; -import { DynamicFormInputMaskControl, DynamicFormInputMaskDefinition } from '@dynamic-forms/core/input-mask'; +import { + DynamicFormInputMaskControl, + DynamicFormInputMaskConverterService, + DynamicFormInputMaskDefinition, +} from '@dynamic-forms/core/input-mask'; import { MockService } from 'ng-mocks'; import { BsDynamicFormInputMaskComponent } from './dynamic-form-input-mask.component'; @@ -41,6 +45,7 @@ describe('BsDynamicFormInputMaskComponent', () => { provide: DynamicFormBuilder, useValue: builder, }, + DynamicFormInputMaskConverterService, ], }); @@ -48,7 +53,7 @@ describe('BsDynamicFormInputMaskComponent', () => { component = fixture.componentInstance; form = new DynamicForm(builder, {} as DynamicFormDefinition, {}); - definition = { key: 'key', template: { label: 'label', input: {} } } as DynamicFormInputMaskDefinition; + definition = { key: 'key', template: { label: 'label', input: { maskOptions: {} } } } as DynamicFormInputMaskDefinition; formControl = new DynamicFormInputMaskControl(builder, form, form, definition, {} as DynamicFormFieldType); component.field = formControl; diff --git a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.spec.ts b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.spec.ts new file mode 100644 index 000000000..e7e3d7b05 --- /dev/null +++ b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.spec.ts @@ -0,0 +1,82 @@ +import { TestBed, TestModuleMetadata, inject } from '@angular/core/testing'; +import { bsDynamicFormLibrary } from '@dynamic-forms/bootstrap'; +import { DYNAMIC_FORM_INPUT_TYPE_CONFIG, DynamicFormInputTypeConfig, provideDynamicForms } from '@dynamic-forms/core'; +import { DynamicFormInputMaskConverterService } from '@dynamic-forms/core/input-mask'; +import { withBsDynamicFormInputMaskConverters } from './dynamic-form-input-mask-converter'; +import { BsDynamicFormInputMaskModule, bsDynamicFormInputMaskType, withBsDynamicFormInputMask } from './dynamic-form-input-mask.module'; + +describe('BsDynamicFormInputMaskModule', () => { + describe('withBsDynamicFormInputMask', () => { + const testModules: { name: string; def: TestModuleMetadata }[] = [ + { + name: 'BsDynamicFormInputMaskModule', + def: { + imports: [BsDynamicFormInputMaskModule], + providers: provideDynamicForms(bsDynamicFormLibrary), + }, + }, + { + name: 'provideDynamicForms', + def: { providers: provideDynamicForms(bsDynamicFormLibrary, withBsDynamicFormInputMask()) }, + }, + ]; + + testModules.forEach(testModule => { + describe(`using ${testModule.name}`, () => { + beforeEach(() => { + TestBed.configureTestingModule(testModule.def); + }); + + it('provides DYNAMIC_FORM_INPUT_TYPE_CONFIG', inject([DYNAMIC_FORM_INPUT_TYPE_CONFIG], (config: DynamicFormInputTypeConfig) => { + expect(config.length).toBe(1); + expect(config[0]).toEqual(bsDynamicFormInputMaskType); + })); + + it('provides DynamicFormInputMaskConverterService with empty converterMap', inject( + [DynamicFormInputMaskConverterService], + (service: DynamicFormInputMaskConverterService) => { + expect(service).toBeDefined(); + expect(service.converterMap.size).toBe(0); + }, + )); + }); + }); + }); + + describe('withBsDynamicFormInputMaskConverters', () => { + const testModules: { name: string; def: TestModuleMetadata }[] = [ + { + name: 'BsDynamicFormInputMaskModule', + def: { + imports: [BsDynamicFormInputMaskModule], + providers: provideDynamicForms(bsDynamicFormLibrary, withBsDynamicFormInputMaskConverters()), + }, + }, + { + name: 'provideDynamicForms', + def: { providers: provideDynamicForms(bsDynamicFormLibrary, withBsDynamicFormInputMask(), withBsDynamicFormInputMaskConverters()) }, + }, + ]; + + testModules.forEach(testModule => { + describe(`using ${testModule.name}`, () => { + beforeEach(() => { + TestBed.configureTestingModule(testModule.def); + }); + + it('provides DYNAMIC_FORM_INPUT_TYPE_CONFIG', inject([DYNAMIC_FORM_INPUT_TYPE_CONFIG], (config: DynamicFormInputTypeConfig) => { + expect(config.length).toBe(1); + expect(config[0]).toEqual(bsDynamicFormInputMaskType); + })); + + it('provides DynamicFormInputMaskConverterService with non-empty converterMap', inject( + [DynamicFormInputMaskConverterService], + (service: DynamicFormInputMaskConverterService) => { + expect(service).toBeDefined(); + expect(service.converterMap.size).toBe(7); + }, + )); + }); + }); + }); +}); diff --git a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.ts b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.ts index 4c98d1ff7..c1ad4a8a7 100644 --- a/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.ts +++ b/libs/bootstrap/input-mask/src/lib/dynamic-form-input-mask.module.ts @@ -1,7 +1,13 @@ import { NgModule } from '@angular/core'; import { bsDynamicFormLibrary } from '@dynamic-forms/bootstrap'; -import { DynamicFormInputType, DynamicFormsFeature, importDynamicFormsProviders, withDynamicFormInputs } from '@dynamic-forms/core'; -import { DynamicFormInputMaskControl } from '@dynamic-forms/core/input-mask'; +import { + DynamicFormInputType, + DynamicFormsFeature, + importDynamicFormsProviders, + mergeDynamicFormsFeatures, + withDynamicFormInputs, +} from '@dynamic-forms/core'; +import { DynamicFormInputMaskControl, withDynamicFormInputMaskConverterService } from '@dynamic-forms/core/input-mask'; import { BsDynamicFormInputMaskComponent } from './dynamic-form-input-mask.component'; export const bsDynamicFormInputMaskType: DynamicFormInputType = { @@ -12,7 +18,7 @@ export const bsDynamicFormInputMaskType: DynamicFormInputType = { }; export function withBsDynamicFormInputMask(): DynamicFormsFeature { - return withDynamicFormInputs(bsDynamicFormInputMaskType); + return mergeDynamicFormsFeatures(withDynamicFormInputs(bsDynamicFormInputMaskType), withDynamicFormInputMaskConverterService()); } /** diff --git a/libs/bootstrap/input-mask/src/public_api.ts b/libs/bootstrap/input-mask/src/public_api.ts index d365db076..9e2a4e5c3 100644 --- a/libs/bootstrap/input-mask/src/public_api.ts +++ b/libs/bootstrap/input-mask/src/public_api.ts @@ -1,2 +1,3 @@ +export * from './lib/dynamic-form-input-mask-converter'; export * from './lib/dynamic-form-input-mask.component'; export * from './lib/dynamic-form-input-mask.module'; diff --git a/libs/bootstrap/package.json b/libs/bootstrap/package.json index 3da4ee246..959ecd9c1 100644 --- a/libs/bootstrap/package.json +++ b/libs/bootstrap/package.json @@ -1,6 +1,6 @@ { "name": "@dynamic-forms/bootstrap", - "version": "18.0.0", + "version": "18.1.0", "author": "dynamic-forms", "description": "dynamic-forms - component library using bootstrap", "keywords": [ @@ -24,7 +24,7 @@ "@angular/common": "^18.0.0", "@angular/core": "^18.0.0", "@angular/forms": "^18.0.0", - "@dynamic-forms/core": "18.0.0", + "@dynamic-forms/core": "18.1.0", "bootstrap": "^5.2.3", "inputmask": "^5.0.8", "rxjs": "^7.4.0" diff --git a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.html b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.html index a284a55bb..a1f992644 100644 --- a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.html +++ b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.html @@ -1,15 +1,14 @@ -
    {{ template.label }} - - +@if (template.url) { + {{ template.label }} +} @else { - - - +} +@if (dialog) { + +} diff --git a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.ts b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.ts index eecf88058..0ce9cd99b 100644 --- a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.ts +++ b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-button/dynamic-form-button.component.ts @@ -1,4 +1,4 @@ -import { NgClass, NgIf } from '@angular/common'; +import { NgClass } from '@angular/common'; import { Component } from '@angular/core'; import { DynamicFormActionService, DynamicFormButtonBase, DynamicFormColorPipe } from '@dynamic-forms/core'; import { BsDynamicFormDialogComponent } from '../../dynamic-form-dialog/dynamic-form-dialog.component'; @@ -7,7 +7,7 @@ import { BsDynamicFormDialogComponent } from '../../dynamic-form-dialog/dynamic- standalone: true, selector: 'bs-dynamic-form-button', templateUrl: './dynamic-form-button.component.html', - imports: [NgClass, NgIf, DynamicFormColorPipe, BsDynamicFormDialogComponent], + imports: [NgClass, DynamicFormColorPipe, BsDynamicFormDialogComponent], }) export class BsDynamicFormButtonComponent extends DynamicFormButtonBase { constructor(protected override actionService: DynamicFormActionService) { diff --git a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.html b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.html index f753f20b3..bade7b180 100644 --- a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.html +++ b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.html @@ -1,17 +1,16 @@
    - - {{ template.icon | dynamicFormIcon }} - - + @if (template.url) { + + {{ template.icon | dynamicFormIcon }} + } @else { - + }
    - - +@if (dialog) { + +} diff --git a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.ts b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.ts index 54e21bcb8..105e1b528 100644 --- a/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.ts +++ b/libs/bootstrap/src/lib/dynamic-form-action/dynamic-form-icon/dynamic-form-icon.component.ts @@ -1,4 +1,4 @@ -import { NgClass, NgIf } from '@angular/common'; +import { NgClass } from '@angular/common'; import { Component } from '@angular/core'; import { DynamicFormActionService, DynamicFormColorPipe, DynamicFormIconBase, DynamicFormIconPipe } from '@dynamic-forms/core'; import { BsDynamicFormDialogComponent } from '../../dynamic-form-dialog/dynamic-form-dialog.component'; @@ -7,7 +7,7 @@ import { BsDynamicFormDialogComponent } from '../../dynamic-form-dialog/dynamic- standalone: true, selector: 'bs-dynamic-form-icon', templateUrl: './dynamic-form-icon.component.html', - imports: [NgClass, NgIf, DynamicFormColorPipe, DynamicFormIconPipe, BsDynamicFormDialogComponent], + imports: [NgClass, DynamicFormColorPipe, DynamicFormIconPipe, BsDynamicFormDialogComponent], }) export class BsDynamicFormIconComponent extends DynamicFormIconBase { constructor(protected override actionService: DynamicFormActionService) { diff --git a/libs/bootstrap/src/lib/dynamic-form-dialog/dynamic-form-dialog.component.html b/libs/bootstrap/src/lib/dynamic-form-dialog/dynamic-form-dialog.component.html index 245b818c3..ede727cdb 100644 --- a/libs/bootstrap/src/lib/dynamic-form-dialog/dynamic-form-dialog.component.html +++ b/libs/bootstrap/src/lib/dynamic-form-dialog/dynamic-form-dialog.component.html @@ -1,41 +1,50 @@ -