Skip to content

Commit cb41ef1

Browse files
committed
Add lifecycle to FormModel
The lifecycle or the lifecycle model may be adjusted depending on the context a form is used in. Add the possibility to pass an object type or a child model of a FormLifecycle in the model of a form. 449831
1 parent 7938143 commit cb41ef1

File tree

3 files changed

+153
-13
lines changed

3 files changed

+153
-13
lines changed

eclipse-scout-core/src/form/Form.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
2+
* Copyright (c) 2010, 2026 BSI Business Systems Integration AG
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -8,10 +8,10 @@
88
* SPDX-License-Identifier: EPL-2.0
99
*/
1010
import {
11-
AbortKeyStroke, App, aria, AriaLabelledByInsertPosition, arrays, BusyIndicatorOptions, Button, ButtonSystemType, DialogLayout, DisabledStyle, DisplayParent, DisplayViewId, EnumObject, ErrorHandler, Event, EventHandler, FileChooser,
12-
FileChooserController, FocusRule, FormController, FormEventMap, FormGrid, FormInvalidEvent, FormLayout, FormLifecycle, FormModel, FormRevealInvalidFieldEvent, GlassPaneRenderer, GroupBox, HtmlComponent, InitModelOf, KeyStroke,
13-
KeyStrokeContext, MessageBox, MessageBoxController, MessageBoxes, NotificationBadgeStatus, ObjectOrChildModel, objects, Point, PopupWindow, PropertyChangeEvent, Rectangle, scout, Status, StatusOrModel, strings, tooltips, TreeVisitResult,
14-
ValidationResult, webstorage, Widget, WrappedFormField
11+
AbortKeyStroke, App, aria, AriaLabelledByInsertPosition, arrays, BusyIndicatorOptions, Button, ButtonSystemType, ChildModelOf, DialogLayout, DisabledStyle, DisplayParent, DisplayViewId, EnumObject, ErrorHandler, Event, EventHandler,
12+
FileChooser, FileChooserController, FocusRule, FormController, FormEventMap, FormGrid, FormInvalidEvent, FormLayout, FormLifecycle, FormModel, FormRevealInvalidFieldEvent, GlassPaneRenderer, GroupBox, HtmlComponent, InitModelOf,
13+
KeyStroke, KeyStrokeContext, MessageBox, MessageBoxController, MessageBoxes, ModelOf, NotificationBadgeStatus, ObjectOrChildModel, objects, Point, PopupWindow, PropertyChangeEvent, Rectangle, scout, Status, StatusOrModel, strings,
14+
tooltips, TreeVisitResult, ValidationResult, webstorage, Widget, WrappedFormField
1515
} from '../index';
1616
import $ from 'jquery';
1717

@@ -321,13 +321,40 @@ export class Form extends Widget implements FormModel, DisplayParent {
321321
}
322322

323323
protected _createLifecycle(): FormLifecycle {
324-
return scout.create(FormLifecycle, {
325-
widget: this,
324+
// already created
325+
if (this.lifecycle instanceof FormLifecycle) {
326+
return this.lifecycle;
327+
}
328+
329+
const defaultModel: ModelOf<FormLifecycle> = {
326330
askIfNeedSave: this.askIfNeedSave,
331+
askIfNeedSaveText: this.askIfNeedSaveText,
327332
emptyMandatoryElementsText: this.emptyMandatoryElementsText,
328333
invalidElementsErrorText: this.invalidElementsErrorText,
329-
invalidElementsWarningText: this.invalidElementsWarningText,
330-
askIfNeedSaveText: this.askIfNeedSaveText
334+
invalidElementsWarningText: this.invalidElementsWarningText
335+
};
336+
337+
// object type
338+
if (typeof this.lifecycle === 'string' || typeof this.lifecycle === 'function') {
339+
return scout.create(this.lifecycle, {
340+
...defaultModel,
341+
widget: this
342+
});
343+
}
344+
345+
// child model
346+
if (objects.isObject(this.lifecycle)) {
347+
return scout.create({
348+
objectType: FormLifecycle,
349+
...defaultModel,
350+
...(this.lifecycle as ChildModelOf<FormLifecycle>),
351+
widget: this
352+
}) as FormLifecycle;
353+
}
354+
355+
return scout.create(FormLifecycle, {
356+
...defaultModel,
357+
widget: this
331358
});
332359
}
333360

eclipse-scout-core/src/form/FormModel.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/*
2-
* Copyright (c) 2010, 2024 BSI Business Systems Integration AG
2+
* Copyright (c) 2010, 2026 BSI Business Systems Integration AG
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
66
* which is available at https://www.eclipse.org/legal/epl-2.0/
77
*
88
* SPDX-License-Identifier: EPL-2.0
99
*/
10-
import {DisplayHint, DisplayParent, DisplayParentModel, DisplayViewId, Form, FormValidator, GroupBox, ObjectOrChildModel, StatusOrModel, Widget, WidgetModel} from '../index';
10+
import {ChildModelOf, DisplayHint, DisplayParent, DisplayParentModel, DisplayViewId, Form, FormLifecycle, FormValidator, GroupBox, ObjectOrChildModel, ObjectType, StatusOrModel, Widget, WidgetModel} from '../index';
1111

1212
export interface FormModel extends WidgetModel, DisplayParentModel {
1313
/**
@@ -230,4 +230,8 @@ export interface FormModel extends WidgetModel, DisplayParentModel {
230230
* By default, the list is empty.
231231
*/
232232
validators?: FormValidator[];
233+
/**
234+
* Defines the {@link FormLifecycle} that is used for the validation lifecycle of the form.
235+
*/
236+
lifecycle?: ObjectType<FormLifecycle> | ChildModelOf<FormLifecycle>;
233237
}

eclipse-scout-core/test/form/FormSpec.ts

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
*/
1010
import {FormSpecHelper, OutlineSpecHelper, SpecForm} from '../../src/testing/index';
1111
import {
12-
App, CancelMenu, CloseMenu, Dimension, fields, FileChooser, Form, FormFieldMenu, FormModel, InitModelOf, MessageBox, NotificationBadgeStatus, NullWidget, NumberField, ObjectFactory, OkMenu, Outline, Page, Popup, PopupBlockerHandler,
13-
Rectangle, ResetMenu, SaveMenu, scout, SearchMenu, SequenceBox, Session, SplitBox, Status, StringField, strings, TabBox, TabItem, webstorage, WidgetModel, WrappedFormField
12+
App, CancelMenu, CloseMenu, Dimension, fields, FileChooser, Form, FormFieldMenu, FormLifecycle, FormModel, InitModelOf, MessageBox, NotificationBadgeStatus, NullWidget, NumberField, ObjectFactory, OkMenu, Outline, Page, Popup,
13+
PopupBlockerHandler, Rectangle, ResetMenu, SaveMenu, scout, SearchMenu, SequenceBox, Session, SplitBox, Status, StringField, strings, TabBox, TabItem, webstorage, WidgetModel, WrappedFormField
1414
} from '../../src/index';
1515
import {DateField, GroupBox} from '../../src';
1616

@@ -32,6 +32,10 @@ describe('Form', () => {
3232
helper = new FormSpecHelper(session);
3333
outlineHelper = new OutlineSpecHelper(session);
3434
uninstallUnloadHandlers(session);
35+
session.textMap.add('FormSaveChangesQuestion', 'Do you want to save the changes?');
36+
session.textMap.add('FormEmptyMandatoryFieldsMessage', 'The following fields must be filled in:');
37+
session.textMap.add('FormInvalidFieldsMessage', 'The following fields are invalid:');
38+
session.textMap.add('FormInvalidFieldsWarningMessage', 'The following fields have a warning:');
3539
});
3640

3741
afterEach(() => {
@@ -2519,4 +2523,109 @@ describe('Form', () => {
25192523
expect(numberField.value).toBe(null);
25202524
});
25212525
});
2526+
2527+
describe('lifecycle', () => {
2528+
2529+
it('is a FormLifecycle by default', () => {
2530+
let form = scout.create(Form, {parent: session.desktop});
2531+
2532+
expect(form.lifecycle).toBeInstanceOf(FormLifecycle);
2533+
expect(form.lifecycle.widget).toBe(form);
2534+
expect(form.lifecycle.askIfNeedSave).toBeTrue();
2535+
expect(form.lifecycle.askIfNeedSaveText).toBe('Do you want to save the changes?');
2536+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('The following fields must be filled in:');
2537+
expect(form.lifecycle.invalidElementsErrorText).toBe('The following fields are invalid:');
2538+
expect(form.lifecycle.invalidElementsWarningText).toBe('The following fields have a warning:');
2539+
2540+
form = scout.create(Form, {
2541+
parent: session.desktop,
2542+
askIfNeedSave: false,
2543+
askIfNeedSaveText: 'lorem',
2544+
emptyMandatoryElementsText: 'ipsum',
2545+
invalidElementsErrorText: 'dolor',
2546+
invalidElementsWarningText: 'sit'
2547+
});
2548+
2549+
expect(form.lifecycle).toBeInstanceOf(FormLifecycle);
2550+
expect(form.lifecycle.widget).toBe(form);
2551+
expect(form.lifecycle.askIfNeedSave).toBeFalse();
2552+
expect(form.lifecycle.askIfNeedSaveText).toBe('lorem');
2553+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('ipsum');
2554+
expect(form.lifecycle.invalidElementsErrorText).toBe('dolor');
2555+
expect(form.lifecycle.invalidElementsWarningText).toBe('sit');
2556+
});
2557+
2558+
it('can be passed in model as objectType', () => {
2559+
let form = scout.create(Form, {
2560+
parent: session.desktop,
2561+
lifecycle: SpecLifecycle
2562+
});
2563+
2564+
expect(form.lifecycle).toBeInstanceOf(SpecLifecycle);
2565+
expect(form.lifecycle.widget).toBe(form);
2566+
expect(form.lifecycle.askIfNeedSave).toBeTrue();
2567+
expect(form.lifecycle.askIfNeedSaveText).toBe('Do you want to save the changes?');
2568+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('The following fields must be filled in:');
2569+
expect(form.lifecycle.invalidElementsErrorText).toBe('The following fields are invalid:');
2570+
expect(form.lifecycle.invalidElementsWarningText).toBe('The following fields have a warning:');
2571+
2572+
form = scout.create(Form, {
2573+
parent: session.desktop,
2574+
lifecycle: SpecLifecycle,
2575+
askIfNeedSave: false,
2576+
askIfNeedSaveText: 'lorem',
2577+
emptyMandatoryElementsText: 'ipsum',
2578+
invalidElementsErrorText: 'dolor',
2579+
invalidElementsWarningText: 'sit'
2580+
});
2581+
2582+
expect(form.lifecycle).toBeInstanceOf(SpecLifecycle);
2583+
expect(form.lifecycle.widget).toBe(form);
2584+
expect(form.lifecycle.askIfNeedSave).toBeFalse();
2585+
expect(form.lifecycle.askIfNeedSaveText).toBe('lorem');
2586+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('ipsum');
2587+
expect(form.lifecycle.invalidElementsErrorText).toBe('dolor');
2588+
expect(form.lifecycle.invalidElementsWarningText).toBe('sit');
2589+
});
2590+
2591+
it('can be passed in model as child model', () => {
2592+
let form = scout.create(Form, {
2593+
parent: session.desktop,
2594+
lifecycle: {
2595+
objectType: SpecLifecycle
2596+
}
2597+
});
2598+
2599+
expect(form.lifecycle).toBeInstanceOf(SpecLifecycle);
2600+
expect(form.lifecycle.widget).toBe(form);
2601+
expect(form.lifecycle.askIfNeedSave).toBeTrue();
2602+
expect(form.lifecycle.askIfNeedSaveText).toBe('Do you want to save the changes?');
2603+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('The following fields must be filled in:');
2604+
expect(form.lifecycle.invalidElementsErrorText).toBe('The following fields are invalid:');
2605+
expect(form.lifecycle.invalidElementsWarningText).toBe('The following fields have a warning:');
2606+
2607+
form = scout.create(Form, {
2608+
parent: session.desktop,
2609+
lifecycle: {
2610+
objectType: SpecLifecycle,
2611+
askIfNeedSave: false,
2612+
askIfNeedSaveText: 'lorem',
2613+
emptyMandatoryElementsText: 'ipsum',
2614+
invalidElementsErrorText: 'dolor',
2615+
invalidElementsWarningText: 'sit'
2616+
}
2617+
});
2618+
2619+
expect(form.lifecycle).toBeInstanceOf(SpecLifecycle);
2620+
expect(form.lifecycle.widget).toBe(form);
2621+
expect(form.lifecycle.askIfNeedSave).toBeFalse();
2622+
expect(form.lifecycle.askIfNeedSaveText).toBe('lorem');
2623+
expect(form.lifecycle.emptyMandatoryElementsText).toBe('ipsum');
2624+
expect(form.lifecycle.invalidElementsErrorText).toBe('dolor');
2625+
expect(form.lifecycle.invalidElementsWarningText).toBe('sit');
2626+
});
2627+
});
2628+
2629+
class SpecLifecycle extends FormLifecycle {
2630+
}
25222631
});

0 commit comments

Comments
 (0)