@progress/kendo-angular-grid 18.5.0-develop.2 → 18.5.0-develop.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/column-menu/column-menu-item.component.d.ts +3 -4
  2. package/columns/column.component.d.ts +3 -2
  3. package/common/field-datatype.d.ts +9 -0
  4. package/directives.d.ts +5 -3
  5. package/editing/form/dialog-form.component.d.ts +27 -0
  6. package/editing/form/form-formfield.component.d.ts +24 -0
  7. package/editing/form/form.component.d.ts +28 -0
  8. package/editing/form/index.d.ts +8 -0
  9. package/editing/form/models.d.ts +196 -0
  10. package/editing-directives/editing-directive-base.d.ts +10 -3
  11. package/editing-directives/external-editing.directive.d.ts +46 -0
  12. package/esm2022/column-menu/column-menu-item.component.mjs +3 -4
  13. package/esm2022/common/field-datatype.mjs +5 -0
  14. package/esm2022/directives.mjs +8 -1
  15. package/esm2022/editing/edit.service.mjs +1 -1
  16. package/esm2022/editing/form/dialog-form.component.mjs +102 -0
  17. package/esm2022/editing/form/form-formfield.component.mjs +161 -0
  18. package/esm2022/editing/form/form.component.mjs +153 -0
  19. package/esm2022/editing/form/index.mjs +8 -0
  20. package/esm2022/editing/form/models.mjs +5 -0
  21. package/esm2022/editing-directives/editing-directive-base.mjs +33 -5
  22. package/esm2022/editing-directives/external-editing.directive.mjs +130 -0
  23. package/esm2022/grid.component.mjs +55 -8
  24. package/esm2022/grid.module.mjs +15 -11
  25. package/esm2022/index.mjs +1 -0
  26. package/esm2022/localization/messages.mjs +62 -1
  27. package/esm2022/package-metadata.mjs +2 -2
  28. package/esm2022/utils.mjs +1 -1
  29. package/fesm2022/progress-kendo-angular-grid.mjs +669 -39
  30. package/grid.component.d.ts +0 -6
  31. package/grid.module.d.ts +15 -11
  32. package/index.d.ts +3 -0
  33. package/localization/messages.d.ts +46 -1
  34. package/package.json +19 -19
  35. package/schematics/ngAdd/index.js +4 -4
@@ -0,0 +1,102 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Component, Input } from '@angular/core';
6
+ import { DialogActionsComponent, DialogContentBase, DialogRef } from '@progress/kendo-angular-dialog';
7
+ import { FormComponent } from './form.component';
8
+ import { FormGroup } from '@angular/forms';
9
+ import { KENDO_BUTTON } from '@progress/kendo-angular-buttons';
10
+ import { cancelIcon, saveIcon } from '@progress/kendo-svg-icons';
11
+ import { LocalizationService } from '@progress/kendo-angular-l10n';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "@progress/kendo-angular-dialog";
14
+ import * as i2 from "@progress/kendo-angular-l10n";
15
+ import * as i3 from "@progress/kendo-angular-buttons";
16
+ /**
17
+ * @hidden
18
+ */
19
+ export class DialogFormComponent extends DialogContentBase {
20
+ localization;
21
+ controls;
22
+ formGroup;
23
+ formSettings;
24
+ saveIcon = saveIcon;
25
+ cancelIcon = cancelIcon;
26
+ constructor(dialogRef, localization) {
27
+ super(dialogRef);
28
+ this.localization = localization;
29
+ }
30
+ save() {
31
+ this.dialog.close({ text: this.localization.get('externalEditingSaveText') });
32
+ }
33
+ cancel() {
34
+ this.dialog.close({ text: this.localization.get('externalEditingCancelText') });
35
+ }
36
+ messageFor(key) {
37
+ return this.localization.get(key);
38
+ }
39
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DialogFormComponent, deps: [{ token: i1.DialogRef }, { token: i2.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
40
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DialogFormComponent, isStandalone: true, selector: "kendo-grid-dialog-form", inputs: { controls: "controls", formGroup: "formGroup", formSettings: "formSettings" }, usesInheritance: true, ngImport: i0, template: `
41
+ <kendo-grid-external-form
42
+ [controls]="controls"
43
+ [formGroup]="formGroup"
44
+ [formSettings]="formSettings"
45
+ [actionButtons]="false"></kendo-grid-external-form>
46
+ <kendo-dialog-actions [layout]="this.dialog?.dialog?.instance?.actionsLayout">
47
+ <button
48
+ kendoButton
49
+ themeColor="primary"
50
+ [svgIcon]="saveIcon"
51
+ [disabled]="!formGroup.valid"
52
+ (click)="save()"
53
+ >
54
+ {{messageFor('externalEditingSaveText')}}
55
+ </button>
56
+ <button
57
+ kendoButton
58
+ [svgIcon]="cancelIcon"
59
+ (click)="cancel()">
60
+ {{messageFor('externalEditingCancelText')}}
61
+ </button>
62
+ </kendo-dialog-actions>
63
+ `, isInline: true, dependencies: [{ kind: "component", type: FormComponent, selector: "kendo-grid-external-form", inputs: ["controls", "formSettings", "formGroup", "actionButtons"], outputs: ["formSubmit"] }, { kind: "component", type: DialogActionsComponent, selector: "kendo-dialog-actions", inputs: ["actions", "layout"], outputs: ["action"] }, { kind: "component", type: i3.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }] });
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DialogFormComponent, decorators: [{
66
+ type: Component,
67
+ args: [{
68
+ selector: 'kendo-grid-dialog-form',
69
+ standalone: true,
70
+ imports: [FormComponent, DialogActionsComponent, KENDO_BUTTON],
71
+ template: `
72
+ <kendo-grid-external-form
73
+ [controls]="controls"
74
+ [formGroup]="formGroup"
75
+ [formSettings]="formSettings"
76
+ [actionButtons]="false"></kendo-grid-external-form>
77
+ <kendo-dialog-actions [layout]="this.dialog?.dialog?.instance?.actionsLayout">
78
+ <button
79
+ kendoButton
80
+ themeColor="primary"
81
+ [svgIcon]="saveIcon"
82
+ [disabled]="!formGroup.valid"
83
+ (click)="save()"
84
+ >
85
+ {{messageFor('externalEditingSaveText')}}
86
+ </button>
87
+ <button
88
+ kendoButton
89
+ [svgIcon]="cancelIcon"
90
+ (click)="cancel()">
91
+ {{messageFor('externalEditingCancelText')}}
92
+ </button>
93
+ </kendo-dialog-actions>
94
+ `
95
+ }]
96
+ }], ctorParameters: function () { return [{ type: i1.DialogRef }, { type: i2.LocalizationService }]; }, propDecorators: { controls: [{
97
+ type: Input
98
+ }], formGroup: [{
99
+ type: Input
100
+ }], formSettings: [{
101
+ type: Input
102
+ }] } });
@@ -0,0 +1,161 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { KeyValuePipe, NgFor, NgIf } from '@angular/common';
6
+ import { ChangeDetectorRef, Component, Input, ViewChild } from '@angular/core';
7
+ import { KENDO_BUTTON } from '@progress/kendo-angular-buttons';
8
+ import { KENDO_DATEPICKER } from '@progress/kendo-angular-dateinputs';
9
+ import { KENDO_CHECKBOX, KENDO_FORMFIELD, KENDO_NUMERICTEXTBOX, KENDO_TEXTBOX } from '@progress/kendo-angular-inputs';
10
+ import { KENDO_LABELS } from '@progress/kendo-angular-label';
11
+ import { ReactiveFormsModule } from '@angular/forms';
12
+ import { LocalizationService } from '@progress/kendo-angular-l10n';
13
+ import { replaceMessagePlaceholder } from '../../utils';
14
+ import * as i0 from "@angular/core";
15
+ import * as i1 from "@progress/kendo-angular-l10n";
16
+ import * as i2 from "@angular/forms";
17
+ import * as i3 from "@progress/kendo-angular-label";
18
+ import * as i4 from "@progress/kendo-angular-inputs";
19
+ import * as i5 from "@progress/kendo-angular-dateinputs";
20
+ /**
21
+ * @hidden
22
+ */
23
+ export class FormFormFieldComponent {
24
+ localization;
25
+ cdr;
26
+ control;
27
+ floatingLabel;
28
+ showError;
29
+ input;
30
+ constructor(localization, cdr) {
31
+ this.localization = localization;
32
+ this.cdr = cdr;
33
+ }
34
+ // required to avoid ExpressionChangedAfterItHasBeenCheckedError caused by
35
+ // binding to the label's 'for' attribute dynamically
36
+ ngAfterContentInit() {
37
+ this.cdr.detectChanges();
38
+ }
39
+ messageFor(key, errorName, field) {
40
+ return replaceMessagePlaceholder(replaceMessagePlaceholder(this.localization.get(key), 'fieldName', field), 'errorName', errorName);
41
+ }
42
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFormFieldComponent, deps: [{ token: i1.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
43
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FormFormFieldComponent, isStandalone: true, selector: "kendo-form-formfield", inputs: { control: "control", floatingLabel: "floatingLabel", showError: "showError" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: `
44
+ <kendo-formfield
45
+ [orientation]="control.orientation">
46
+ <kendo-floatinglabel
47
+ *ngIf="control.label && floatingLabel && $any(control.dataType) !== 'boolean'"
48
+ labelCssClass="k-form-label"
49
+ [text]="control.label">
50
+ <kendo-textbox
51
+ *ngIf="$any(control.dataType) === 'text'"
52
+ [formControl]="control.formControl"></kendo-textbox>
53
+ <kendo-numerictextbox
54
+ *ngIf="$any(control.dataType) === 'numeric'"
55
+ [formControl]="control.formControl"></kendo-numerictextbox>
56
+ <kendo-datepicker
57
+ *ngIf="$any(control.dataType) === 'date'"
58
+ [formControl]="control.formControl"></kendo-datepicker>
59
+ </kendo-floatinglabel>
60
+ <kendo-label [style.align-items]="'start'"
61
+ *ngIf="control.label && !floatingLabel && $any(control.dataType) !== 'boolean'"
62
+ labelCssClass="k-form-label"
63
+ [text]="control.label"
64
+ [for]="input">
65
+ </kendo-label>
66
+ <kendo-textbox #input
67
+ *ngIf="!floatingLabel && (control.dataType) === 'text'"
68
+ [formControl]="control.formControl"></kendo-textbox>
69
+ <kendo-numerictextbox #input
70
+ *ngIf="!floatingLabel && $any(control.dataType) === 'numeric'"
71
+ [formControl]="control.formControl"></kendo-numerictextbox>
72
+ <kendo-datepicker #input
73
+ *ngIf="!floatingLabel && $any(control.dataType) === 'date'"
74
+ [formControl]="control.formControl"></kendo-datepicker>
75
+ <div
76
+ *ngIf="control.label && $any(control.dataType) === 'boolean'"
77
+ class="k-form-field-checkbox-wrap">
78
+ <kendo-checkbox #cb [formControl]="control.formControl"></kendo-checkbox>
79
+ <kendo-label
80
+ *ngIf="control.label"
81
+ class="k-checkbox-label"
82
+ [for]="cb"
83
+ [text]="control.label">
84
+ </kendo-label>
85
+ </div>
86
+
87
+ <kendo-formhint *ngIf="control?.hint">{{control.hint}}</kendo-formhint>
88
+ <ng-container *ngIf="showError && control.formControl?.invalid && control.formControl.touched">
89
+ <kendo-formerror *ngFor="let err of control?.formControl?.errors | keyvalue">{{control.errors ? control.errors[err.key] : messageFor('formValidationError', err.key, control.name)}}</kendo-formerror>
90
+ </ng-container>
91
+ </kendo-formfield>
92
+ `, isInline: true, dependencies: [{ kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3.LabelComponent, selector: "kendo-label", inputs: ["text", "for", "optional", "labelCssStyle", "labelCssClass"], exportAs: ["kendoLabel"] }, { kind: "component", type: i3.FloatingLabelComponent, selector: "kendo-floatinglabel", inputs: ["labelCssStyle", "labelCssClass", "id", "text", "optional"], outputs: ["positionChange"], exportAs: ["kendoFloatingLabel"] }, { kind: "component", type: i4.FormFieldComponent, selector: "kendo-formfield", inputs: ["showHints", "orientation", "showErrors"] }, { kind: "component", type: i4.HintComponent, selector: "kendo-formhint", inputs: ["align"] }, { kind: "component", type: i4.ErrorComponent, selector: "kendo-formerror", inputs: ["align"] }, { kind: "component", type: i4.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i4.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "component", type: i4.CheckBoxComponent, selector: "kendo-checkbox", inputs: ["checkedState", "rounded"], outputs: ["checkedStateChange"], exportAs: ["kendoCheckBox"] }, { kind: "component", type: i5.DatePickerComponent, selector: "kendo-datepicker", inputs: ["focusableId", "cellTemplate", "clearButton", "inputAttributes", "monthCellTemplate", "yearCellTemplate", "decadeCellTemplate", "centuryCellTemplate", "weekNumberTemplate", "headerTitleTemplate", "headerTemplate", "footerTemplate", "footer", "navigationItemTemplate", "weekDaysFormat", "showOtherMonthDays", "activeView", "bottomView", "topView", "calendarType", "animateCalendarNavigation", "disabled", "readonly", "readOnlyInput", "popupSettings", "navigation", "min", "max", "incompleteDateValidation", "autoCorrectParts", "autoSwitchParts", "autoSwitchKeys", "enableMouseWheel", "allowCaretMode", "autoFill", "focusedDate", "value", "format", "twoDigitYearMax", "formatPlaceholder", "placeholder", "tabindex", "tabIndex", "disabledDates", "title", "subtitle", "rangeValidation", "disabledDatesValidation", "weekNumber", "size", "rounded", "fillMode", "adaptiveMode"], outputs: ["valueChange", "focus", "blur", "open", "close", "escape"], exportAs: ["kendo-datepicker"] }] });
93
+ }
94
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFormFieldComponent, decorators: [{
95
+ type: Component,
96
+ args: [{
97
+ selector: 'kendo-form-formfield',
98
+ standalone: true,
99
+ imports: [KeyValuePipe, NgFor, NgIf, ReactiveFormsModule,
100
+ KENDO_LABELS, KENDO_FORMFIELD, KENDO_TEXTBOX, KENDO_NUMERICTEXTBOX, KENDO_BUTTON, KENDO_CHECKBOX, KENDO_DATEPICKER],
101
+ template: `
102
+ <kendo-formfield
103
+ [orientation]="control.orientation">
104
+ <kendo-floatinglabel
105
+ *ngIf="control.label && floatingLabel && $any(control.dataType) !== 'boolean'"
106
+ labelCssClass="k-form-label"
107
+ [text]="control.label">
108
+ <kendo-textbox
109
+ *ngIf="$any(control.dataType) === 'text'"
110
+ [formControl]="control.formControl"></kendo-textbox>
111
+ <kendo-numerictextbox
112
+ *ngIf="$any(control.dataType) === 'numeric'"
113
+ [formControl]="control.formControl"></kendo-numerictextbox>
114
+ <kendo-datepicker
115
+ *ngIf="$any(control.dataType) === 'date'"
116
+ [formControl]="control.formControl"></kendo-datepicker>
117
+ </kendo-floatinglabel>
118
+ <kendo-label [style.align-items]="'start'"
119
+ *ngIf="control.label && !floatingLabel && $any(control.dataType) !== 'boolean'"
120
+ labelCssClass="k-form-label"
121
+ [text]="control.label"
122
+ [for]="input">
123
+ </kendo-label>
124
+ <kendo-textbox #input
125
+ *ngIf="!floatingLabel && (control.dataType) === 'text'"
126
+ [formControl]="control.formControl"></kendo-textbox>
127
+ <kendo-numerictextbox #input
128
+ *ngIf="!floatingLabel && $any(control.dataType) === 'numeric'"
129
+ [formControl]="control.formControl"></kendo-numerictextbox>
130
+ <kendo-datepicker #input
131
+ *ngIf="!floatingLabel && $any(control.dataType) === 'date'"
132
+ [formControl]="control.formControl"></kendo-datepicker>
133
+ <div
134
+ *ngIf="control.label && $any(control.dataType) === 'boolean'"
135
+ class="k-form-field-checkbox-wrap">
136
+ <kendo-checkbox #cb [formControl]="control.formControl"></kendo-checkbox>
137
+ <kendo-label
138
+ *ngIf="control.label"
139
+ class="k-checkbox-label"
140
+ [for]="cb"
141
+ [text]="control.label">
142
+ </kendo-label>
143
+ </div>
144
+
145
+ <kendo-formhint *ngIf="control?.hint">{{control.hint}}</kendo-formhint>
146
+ <ng-container *ngIf="showError && control.formControl?.invalid && control.formControl.touched">
147
+ <kendo-formerror *ngFor="let err of control?.formControl?.errors | keyvalue">{{control.errors ? control.errors[err.key] : messageFor('formValidationError', err.key, control.name)}}</kendo-formerror>
148
+ </ng-container>
149
+ </kendo-formfield>
150
+ `
151
+ }]
152
+ }], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { control: [{
153
+ type: Input
154
+ }], floatingLabel: [{
155
+ type: Input
156
+ }], showError: [{
157
+ type: Input
158
+ }], input: [{
159
+ type: ViewChild,
160
+ args: ['input']
161
+ }] } });
@@ -0,0 +1,153 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
6
+ import { ReactiveFormsModule, FormGroup } from '@angular/forms';
7
+ import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
8
+ import { KENDO_BUTTON } from '@progress/kendo-angular-buttons';
9
+ import { cancelIcon, saveIcon } from '@progress/kendo-svg-icons';
10
+ import { FormFormFieldComponent } from './form-formfield.component';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
13
+ import * as i2 from "@progress/kendo-angular-buttons";
14
+ let idx = 0;
15
+ /**
16
+ * @hidden
17
+ */
18
+ export class FormComponent {
19
+ controls = [];
20
+ set formSettings(value) {
21
+ this._formSettings = { ...this._formSettings, ...value };
22
+ }
23
+ get formSettings() {
24
+ return this._formSettings;
25
+ }
26
+ formGroup;
27
+ set actionButtons(value) {
28
+ if (typeof value === 'boolean') {
29
+ this.normalizeActionButtonSettings(value);
30
+ }
31
+ else {
32
+ this._actionButtons = value;
33
+ }
34
+ }
35
+ get actionButtons() {
36
+ return this._actionButtons;
37
+ }
38
+ formSubmit = new EventEmitter();
39
+ get componentIndex() {
40
+ return idx++;
41
+ }
42
+ _formSettings = {
43
+ orientation: 'vertical',
44
+ showErrors: true,
45
+ floatingLabels: false
46
+ };
47
+ defaultActionButtons = [{
48
+ actionType: 'submit',
49
+ text: 'Submit',
50
+ svgIcon: saveIcon,
51
+ icon: 'save',
52
+ themeColor: 'primary'
53
+ }, {
54
+ actionType: 'reset',
55
+ svgIcon: cancelIcon,
56
+ text: 'Reset',
57
+ icon: 'cancel'
58
+ }];
59
+ _actionButtons = this.defaultActionButtons;
60
+ ngOnInit() {
61
+ idx++;
62
+ }
63
+ normalizeActionButtonSettings(value) {
64
+ this._actionButtons = value ? this.defaultActionButtons : [];
65
+ }
66
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
67
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FormComponent, isStandalone: true, selector: "kendo-grid-external-form", inputs: { controls: "controls", formSettings: "formSettings", formGroup: "formGroup", actionButtons: "actionButtons" }, outputs: { formSubmit: "formSubmit" }, ngImport: i0, template: `
68
+ <div role="form"
69
+ class="k-form k-form-md"
70
+ [class.k-form-horizontal]="formSettings.orientation === 'horizontal'"
71
+ [formGroup]="formGroup"
72
+ (ngSubmit)="formSubmit.next({originalEvent: $event, formGroup})"
73
+ (reset)="$event.preventDefault()">
74
+ <ng-container *ngFor="let control of controls; let idx = index;">
75
+ <ng-container *ngIf="!control.template; else template">
76
+ <kendo-form-formfield
77
+ [control]="control"
78
+ [showError]="formSettings.showErrors"
79
+ [floatingLabel]="formSettings.floatingLabels"></kendo-form-formfield>
80
+ </ng-container>
81
+ <ng-template #template>
82
+ <ng-container
83
+ [ngTemplateOutlet]="control.template"
84
+ [ngTemplateOutletContext]="control.templateContext"></ng-container>
85
+ </ng-template>
86
+ </ng-container>
87
+ <div class="k-form-buttons" *ngIf="$any(actionButtons).length">
88
+ <button kendoButton *ngFor="let button of $any(actionButtons)"
89
+ [class.k-form-submit]="button.actionType === 'submit'"
90
+ [size]="button.size"
91
+ [themeColor]="button.themeColor || button.actionType === 'submit' ? 'primary' : undefined"
92
+ [rounded]="button.rounded"
93
+ [attr.type]="button.actionType"
94
+ [svgIcon]="button.svgIcon"
95
+ [icon]="button.icon">
96
+ {{button.text}}
97
+ </button>
98
+ </div>
99
+ </div>
100
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormFormFieldComponent, selector: "kendo-form-formfield", inputs: ["control", "floatingLabel", "showError"] }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }] });
101
+ }
102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormComponent, decorators: [{
103
+ type: Component,
104
+ args: [{
105
+ selector: 'kendo-grid-external-form',
106
+ standalone: true,
107
+ template: `
108
+ <div role="form"
109
+ class="k-form k-form-md"
110
+ [class.k-form-horizontal]="formSettings.orientation === 'horizontal'"
111
+ [formGroup]="formGroup"
112
+ (ngSubmit)="formSubmit.next({originalEvent: $event, formGroup})"
113
+ (reset)="$event.preventDefault()">
114
+ <ng-container *ngFor="let control of controls; let idx = index;">
115
+ <ng-container *ngIf="!control.template; else template">
116
+ <kendo-form-formfield
117
+ [control]="control"
118
+ [showError]="formSettings.showErrors"
119
+ [floatingLabel]="formSettings.floatingLabels"></kendo-form-formfield>
120
+ </ng-container>
121
+ <ng-template #template>
122
+ <ng-container
123
+ [ngTemplateOutlet]="control.template"
124
+ [ngTemplateOutletContext]="control.templateContext"></ng-container>
125
+ </ng-template>
126
+ </ng-container>
127
+ <div class="k-form-buttons" *ngIf="$any(actionButtons).length">
128
+ <button kendoButton *ngFor="let button of $any(actionButtons)"
129
+ [class.k-form-submit]="button.actionType === 'submit'"
130
+ [size]="button.size"
131
+ [themeColor]="button.themeColor || button.actionType === 'submit' ? 'primary' : undefined"
132
+ [rounded]="button.rounded"
133
+ [attr.type]="button.actionType"
134
+ [svgIcon]="button.svgIcon"
135
+ [icon]="button.icon">
136
+ {{button.text}}
137
+ </button>
138
+ </div>
139
+ </div>
140
+ `,
141
+ imports: [NgFor, NgIf, NgTemplateOutlet, ReactiveFormsModule, FormFormFieldComponent, KENDO_BUTTON],
142
+ }]
143
+ }], propDecorators: { controls: [{
144
+ type: Input
145
+ }], formSettings: [{
146
+ type: Input
147
+ }], formGroup: [{
148
+ type: Input
149
+ }], actionButtons: [{
150
+ type: Input
151
+ }], formSubmit: [{
152
+ type: Output
153
+ }] } });
@@ -0,0 +1,8 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ export * from './models';
6
+ export * from './form.component';
7
+ export * from './dialog-form.component';
8
+ export * from './form-formfield.component';
@@ -0,0 +1,5 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ export {};
@@ -2,12 +2,15 @@
2
2
  * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { Input, Directive } from '@angular/core';
5
+ import { Input, Directive, inject } from '@angular/core';
6
6
  import { GridComponent } from '../grid.component';
7
7
  import { LocalEditService } from './local-edit.service';
8
- import { Subscription, Observable } from 'rxjs';
8
+ import { Subscription, Observable, Subject } from 'rxjs';
9
9
  import { LocalDataChangesService } from '../editing/local-data-changes.service';
10
10
  import { take } from 'rxjs/operators';
11
+ import { DialogService } from '@progress/kendo-angular-dialog';
12
+ import { checkIcon, xIcon } from '@progress/kendo-svg-icons';
13
+ import { LocalizationService } from '@progress/kendo-angular-l10n';
11
14
  import * as i0 from "@angular/core";
12
15
  import * as i1 from "../grid.component";
13
16
  import * as i2 from "../editing/local-data-changes.service";
@@ -28,10 +31,32 @@ export class EditingDirectiveBase {
28
31
  get editService() {
29
32
  return this.userEditService || this.defaultEditService;
30
33
  }
34
+ removeConfirmationSubject = new Subject();
35
+ dialogService;
36
+ localization;
37
+ defaultRemoveConfirmation = (_item) => {
38
+ const dialog = this.dialogService.open({
39
+ title: this.localization.get('removeConfirmationDialogTitle'),
40
+ content: this.localization.get('removeConfirmationDialogContent'),
41
+ actions: [{
42
+ text: this.localization.get('removeConfirmationDialogConfirmText'),
43
+ themeColor: 'primary',
44
+ svgIcon: checkIcon,
45
+ icon: 'check'
46
+ }, {
47
+ text: this.localization.get('removeConfirmationDialogRejectText'),
48
+ svgIcon: xIcon,
49
+ icon: 'x'
50
+ }],
51
+ });
52
+ dialog.result.pipe(take(1)).subscribe((e) => this.removeConfirmationSubject.next(e.text === this.localization.get('removeConfirmationDialogConfirmText')));
53
+ return this.removeConfirmationSubject;
54
+ };
31
55
  /**
32
56
  * A function that is called to confirm if the `dataItem` will be removed.
57
+ * Setting to `true` will result in displaying a default confirmation dialog.
33
58
  */
34
- removeConfirmation;
59
+ removeConfirmation = false;
35
60
  subscriptions = new Subscription();
36
61
  defaultEditService;
37
62
  userEditService;
@@ -39,6 +64,8 @@ export class EditingDirectiveBase {
39
64
  this.grid = grid;
40
65
  this.localDataChangesService = localDataChangesService;
41
66
  this.defaultEditService = this.createDefaultService();
67
+ this.dialogService = inject(DialogService);
68
+ this.localization = inject(LocalizationService);
42
69
  }
43
70
  /**
44
71
  * @hidden
@@ -59,7 +86,7 @@ export class EditingDirectiveBase {
59
86
  createDefaultService() {
60
87
  return new LocalEditService(this.grid, this.localDataChangesService);
61
88
  }
62
- addHandler() {
89
+ addHandler(_args) {
63
90
  this.grid.addRow(this.createModel({ isNew: true }));
64
91
  }
65
92
  saveHandler(args) {
@@ -84,7 +111,8 @@ export class EditingDirectiveBase {
84
111
  }
85
112
  };
86
113
  if (this.removeConfirmation) {
87
- const result = this.removeConfirmation(dataItem);
114
+ const confirmationCallback = typeof this.removeConfirmation === 'boolean' ? this.defaultRemoveConfirmation : this.removeConfirmation;
115
+ const result = confirmationCallback(dataItem);
88
116
  if (result instanceof Promise) {
89
117
  result.then(removeItem);
90
118
  }
@@ -0,0 +1,130 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, Input } from '@angular/core';
6
+ import { GridComponent } from '../grid.component';
7
+ import { LocalDataChangesService } from '../editing/local-data-changes.service';
8
+ import { markAllAsTouched } from './utils';
9
+ import { EditingDirectiveBase } from './editing-directive-base';
10
+ import { DialogFormComponent } from '../editing/form';
11
+ import { isPresent } from '@progress/kendo-angular-common';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "../grid.component";
14
+ import * as i2 from "../editing/local-data-changes.service";
15
+ /**
16
+ * A directive which encapsulates the editing operations of the Grid when using the
17
+ * External Form ([see example](slug:editing_directives_grid#external-editing)).
18
+ */
19
+ export class ExternalEditingDirective extends EditingDirectiveBase {
20
+ grid;
21
+ localDataChangesService;
22
+ /**
23
+ * The function that creates the `FormGroup` for the edited model.
24
+ */
25
+ createFormGroup;
26
+ /**
27
+ * Allows you to customize form orientation, hints, labels and error messages.
28
+ */
29
+ formSettings;
30
+ /**
31
+ * Allows you to customize the Dialog that contains the edit form.
32
+ */
33
+ dialogSettings;
34
+ constructor(grid, localDataChangesService) {
35
+ super(grid, localDataChangesService);
36
+ this.grid = grid;
37
+ this.localDataChangesService = localDataChangesService;
38
+ }
39
+ ngOnInit() {
40
+ super.ngOnInit();
41
+ this.subscriptions
42
+ .add(this.grid.edit.subscribe(this.editHandler.bind(this)));
43
+ }
44
+ /**
45
+ * @hidden
46
+ * Opens a Dialog that contains the edit form.
47
+ */
48
+ openEditFormDialog(editEventArgs, formGroup, formSettings) {
49
+ const settings = { content: DialogFormComponent, title: this.localization.get('externalEditingTitle'), ...this.dialogSettings };
50
+ const dialog = this.dialogService.open(settings);
51
+ const formControls = this.normalizeFormSettings(formGroup, editEventArgs);
52
+ dialog.content.setInput('controls', formControls);
53
+ formSettings && dialog.content.setInput('formSettings', formSettings);
54
+ dialog.content.setInput('formGroup', formGroup);
55
+ dialog.result.subscribe((r) => {
56
+ const resultType = r['text'];
57
+ if (resultType === this.localization.get('externalEditingSaveText')) {
58
+ this.saveHandler({ ...editEventArgs, formGroup });
59
+ }
60
+ dialog.close();
61
+ });
62
+ }
63
+ createModel(args) {
64
+ return this.createFormGroup(args);
65
+ }
66
+ editHandler(args) {
67
+ const formGroup = this.createModel(args);
68
+ this.openEditFormDialog(args, formGroup, this.formSettings);
69
+ }
70
+ saveModel({ dataItem, formGroup, isNew }) {
71
+ if (!formGroup.dirty && !isNew) {
72
+ return;
73
+ }
74
+ if (formGroup.valid) {
75
+ const item = dataItem || [];
76
+ this.editService.assignValues(item, formGroup.value);
77
+ return item;
78
+ }
79
+ markAllAsTouched(formGroup);
80
+ }
81
+ addHandler(args) {
82
+ const formGroup = this.createModel(args);
83
+ this.openEditFormDialog(args, formGroup, this.formSettings);
84
+ }
85
+ normalizeFormSettings(args, editEventArgs) {
86
+ const editableColumnFields = this.grid.columns.toArray().filter(c => c.field && c.editable && isPresent(args.get(c.field))).map(c => c.field);
87
+ const settings = editableColumnFields.map(k => {
88
+ const column = this.grid.columns.toArray().find(c => c.field === k);
89
+ const title = column.title || k;
90
+ const template = column.editTemplateRef;
91
+ const templateContext = template ? {
92
+ $implicit: args,
93
+ isNew: editEventArgs.isNew,
94
+ column,
95
+ dataItem: editEventArgs.dataItem,
96
+ formGroup: args,
97
+ rowIndex: editEventArgs.rowIndex
98
+ } : null;
99
+ const customSettings = this.formSettings?.fields?.[k];
100
+ return {
101
+ name: k,
102
+ label: customSettings?.label || title,
103
+ hint: customSettings?.hint,
104
+ errors: customSettings?.errors,
105
+ formControl: args.get(k),
106
+ dataType: column.editor,
107
+ orientation: this.formSettings?.orientation || 'vertical',
108
+ template: template,
109
+ templateContext: templateContext
110
+ };
111
+ });
112
+ return settings.filter(item => isPresent(item));
113
+ }
114
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ExternalEditingDirective, deps: [{ token: i1.GridComponent }, { token: i2.LocalDataChangesService }], target: i0.ɵɵFactoryTarget.Directive });
115
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ExternalEditingDirective, isStandalone: true, selector: "[kendoGridExternalEditing]", inputs: { createFormGroup: ["kendoGridExternalEditing", "createFormGroup"], formSettings: "formSettings", dialogSettings: "dialogSettings" }, usesInheritance: true, ngImport: i0 });
116
+ }
117
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ExternalEditingDirective, decorators: [{
118
+ type: Directive,
119
+ args: [{
120
+ selector: '[kendoGridExternalEditing]',
121
+ standalone: true
122
+ }]
123
+ }], ctorParameters: function () { return [{ type: i1.GridComponent }, { type: i2.LocalDataChangesService }]; }, propDecorators: { createFormGroup: [{
124
+ type: Input,
125
+ args: ['kendoGridExternalEditing']
126
+ }], formSettings: [{
127
+ type: Input
128
+ }], dialogSettings: [{
129
+ type: Input
130
+ }] } });