Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Villiger2021-05-20 12:04:18 +0000
committerMatthias Villiger2021-05-27 09:14:24 +0000
commit39192bb0e5bc5c5e03f174c31765e543d33f52ef (patch)
tree14b82ff57b0ae2886e5a93200846ad4763df84a7
parent19f968c5fed17c669ac90c94c9cf395ae90d780a (diff)
downloadorg.eclipse.scout.rt-39192bb0e5bc5c5e03f174c31765e543d33f52ef.tar.gz
org.eclipse.scout.rt-39192bb0e5bc5c5e03f174c31765e543d33f52ef.tar.xz
org.eclipse.scout.rt-39192bb0e5bc5c5e03f174c31765e543d33f52ef.zip
Lazily create detailForm and detailTable for Scout JS pages
-rw-r--r--eclipse-scout-core/src/desktop/outline/Outline.js26
-rw-r--r--eclipse-scout-core/src/desktop/outline/OutlineAdapter.js4
-rw-r--r--eclipse-scout-core/src/desktop/outline/pages/Page.js258
-rw-r--r--eclipse-scout-core/src/desktop/outline/pages/PageWithNodes.js7
-rw-r--r--eclipse-scout-core/src/desktop/outline/pages/PageWithTable.js39
-rw-r--r--eclipse-scout-core/src/widget/Widget.js3
-rw-r--r--eclipse-scout-core/test/desktop/outline/pages/PageSpec.js113
-rw-r--r--eclipse-scout-core/test/desktop/outline/pages/PageWithTableSpec.js3
-rw-r--r--scout-hellojs-app/src/main/resources/archetype-resources/__rootArtifactId__.ui/src/main/js/person/PersonTablePage.js7
9 files changed, 383 insertions, 77 deletions
diff --git a/eclipse-scout-core/src/desktop/outline/Outline.js b/eclipse-scout-core/src/desktop/outline/Outline.js
index c08c3851bf..71b58cd2a7 100644
--- a/eclipse-scout-core/src/desktop/outline/Outline.js
+++ b/eclipse-scout-core/src/desktop/outline/Outline.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018 BSI Business Systems Integration AG.
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -602,8 +602,10 @@ export default class Outline extends Tree {
}
_appendNavigateButtonsForDetailForm(node) {
- let menus = this._createNavigateButtons(node, node.detailForm.rootGroupBox);
- node.detailForm.rootGroupBox.setStaticMenus(menus);
+ if (node.detailForm.rootGroupBox) {
+ let menus = this._createNavigateButtons(node, node.detailForm.rootGroupBox);
+ node.detailForm.rootGroupBox.setStaticMenus(menus);
+ }
}
_appendNavigateButtonsForDetailTable(node) {
@@ -612,10 +614,12 @@ export default class Outline extends Tree {
}
_removeNavigateButtonsForDetailForm(node) {
- let staticMenus = node.detailForm.rootGroupBox.staticMenus.filter(menu => {
- return !(menu instanceof NavigateButton);
- });
- node.detailForm.rootGroupBox.setStaticMenus(staticMenus);
+ if (node.detailForm.rootGroupBox) {
+ let staticMenus = node.detailForm.rootGroupBox.staticMenus.filter(menu => {
+ return !(menu instanceof NavigateButton);
+ });
+ node.detailForm.rootGroupBox.setStaticMenus(staticMenus);
+ }
}
_removeNavigateButtonsForDetailTable(node) {
@@ -885,9 +889,11 @@ export default class Outline extends Tree {
if (this.detailContent && this.detailContent instanceof Form) {
// Get menus from detail form
let rootGroupBox = this.detailContent.rootGroupBox;
- menuItems = rootGroupBox.processMenus.concat(rootGroupBox.menus);
- rootGroupBox.setMenuBarVisible(false);
- this._attachDetailMenusListener(rootGroupBox);
+ if (rootGroupBox) {
+ menuItems = rootGroupBox.processMenus.concat(rootGroupBox.menus);
+ rootGroupBox.setMenuBarVisible(false);
+ this._attachDetailMenusListener(rootGroupBox);
+ }
} else if (selectedPage && !(this.detailContent instanceof OutlineOverview)) {
// Get empty space menus and table controls from detail table
// DetailContent can be null or it is the tableRowDetail. Don't show menus on OutlineOverview.
diff --git a/eclipse-scout-core/src/desktop/outline/OutlineAdapter.js b/eclipse-scout-core/src/desktop/outline/OutlineAdapter.js
index 99b2977c2b..9d42ec0852 100644
--- a/eclipse-scout-core/src/desktop/outline/OutlineAdapter.js
+++ b/eclipse-scout-core/src/desktop/outline/OutlineAdapter.js
@@ -27,9 +27,7 @@ export default class OutlineAdapter extends TreeAdapter {
page.detailFormVisible = event.detailFormVisible;
let detailForm = this.session.getOrCreateWidget(event.detailForm, this.widget);
- if (detailForm !== page.detailForm) {
- page.setDetailForm(detailForm);
- }
+ page.setDetailForm(detailForm);
page.navigateButtonsVisible = event.navigateButtonsVisible;
page.detailTableVisible = event.detailTableVisible;
diff --git a/eclipse-scout-core/src/desktop/outline/pages/Page.js b/eclipse-scout-core/src/desktop/outline/pages/Page.js
index 0bf0799a26..f9f89481d3 100644
--- a/eclipse-scout-core/src/desktop/outline/pages/Page.js
+++ b/eclipse-scout-core/src/desktop/outline/pages/Page.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020 BSI Business Systems Integration AG.
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,7 +8,7 @@
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
-import {icons, inspector, MenuBar, Outline, TableRow, TileOutlineOverview, TreeNode} from '../../../index';
+import {Event, EventSupport, Form, icons, inspector, MenuBar, Outline, TableRow, scout, TileOutlineOverview, TileOverviewForm, TreeNode, Widget} from '../../../index';
import $ from 'jquery';
/**
@@ -38,10 +38,6 @@ export default class Page extends TreeNode {
this.detailFormVisibleByUi = true;
this.navigateButtonsVisible = true;
- /**
- * This property contains the class-name of the form to be instantiated, when createDetailForm() is called.
- */
- this.detailFormType = null;
this.tableStatusVisible = true;
/**
* True to select the page linked with the selected row when the row was selected. May be useful on touch devices.
@@ -52,6 +48,14 @@ export default class Page extends TreeNode {
*/
this.overviewIconId = null;
this.showTileOverview = false;
+ this.events = new EventSupport();
+ this.events.registerSubTypePredicate('propertyChange', (event, propertyName) => {
+ return event.propertyName === propertyName;
+ });
+ this._tableFilterHandler = this._onTableFilter.bind(this);
+ this._tableRowClickHandler = this._onTableRowClick.bind(this);
+ this._detailTableModel = null;
+ this._detailFormModel = null;
}
/**
@@ -67,23 +71,36 @@ export default class Page extends TreeNode {
};
/**
- * Override this function to return a detail form which is displayed in the outline when this page is selected.
- * The default impl. returns null.
- */
- createDetailForm() {
- return null;
- }
-
- /**
* @override TreeNode.js
*/
_init(model) {
+ this._detailTableModel = Page._removePropertyIfLazyLoading(model, 'detailTable');
+ this._detailFormModel = Page._removePropertyIfLazyLoading(model, 'detailForm');
+
super._init(model);
icons.resolveIconProperty(this, 'overviewIconId');
+
+ // init necessary if the properties are still available (e.g. Scout classic)
this._internalInitTable();
this._internalInitDetailForm();
}
+ static _removePropertyIfLazyLoading(object, name) {
+ let prop = object[name];
+ if (typeof prop === 'string') {
+ // Scout Classic: it is an object id -> do not remove it. directly create the widget. lazy loading is done on backend
+ return null;
+ }
+ if (prop instanceof Widget) {
+ // it already is a widget. directly use it.
+ return null;
+ }
+
+ // otherwise: remove the property and return it
+ delete object[name];
+ return prop;
+ }
+
/**
* @override TreeNode.js
*/
@@ -98,55 +115,139 @@ export default class Page extends TreeNode {
}
_internalInitTable() {
- let table = this.detailTable;
- if (table) {
+ let tableModel = this.detailTable;
+ if (tableModel) {
// this case is used for Scout classic
- table = this.getOutline()._createChild(table);
- } else {
- table = this._createTable();
+ let newDetailTable = this.getOutline()._createChild(tableModel);
+ this._setDetailTable(newDetailTable);
}
-
- this.setDetailTable(table);
}
_internalInitDetailForm() {
- let detailForm = this.detailForm;
- if (detailForm) {
- detailForm = this.getOutline()._createChild(detailForm);
+ let formModel = this.detailForm;
+ if (formModel) {
+ let newDetailForm = this.getOutline()._createChild(formModel);
+ this._setDetailForm(newDetailForm);
}
+ }
- this.setDetailForm(detailForm);
+ ensureDetailTable() {
+ if (this.detailTable) {
+ return;
+ }
+ this.setDetailTable(this.createDetailTable());
+ }
+
+ /**
+ * Creates the detail table
+ * @returns {Table} the created table or null
+ */
+ createDetailTable() {
+ let detailTable = this._createDetailTable();
+ if (!detailTable && this._detailTableModel) {
+ detailTable = this.getOutline()._createChild(this._detailTableModel);
+ this._detailTableModel = null; // no longer needed
+ }
+ return detailTable;
}
/**
* Override this function to create the internal table. Default impl. returns null.
+ *
+ * @returns {Table}
+ */
+ _createDetailTable() {
+ return null;
+ }
+
+ ensureDetailForm() {
+ if (this.detailForm) {
+ return;
+ }
+ this.setDetailForm(this.createDetailForm());
+ }
+
+ /**
+ * Creates the detail form
+ * @returns {Form|*} the created form or null
+ */
+ createDetailForm() {
+ let detailForm = this._createDetailForm();
+ if (!detailForm && this._detailFormModel) {
+ detailForm = this.getOutline()._createChild(this._detailFormModel);
+ this._detailFormModel = null; // no longer needed
+ }
+ return detailForm;
+ }
+
+ /**
+ * Override this function to return a detail form which is displayed in the outline when this page is selected.
+ * The default implementation returns null.
+ *
+ * @returns {Form|*}
*/
- _createTable() {
+ _createDetailForm() {
return null;
}
/**
- * Override this function to initialize the internal (detail) table. Default impl. delegates
- * <code>filter</code> events to the outline mediator.
+ * Override this function to initialize the internal detail form.
+ * @param {Form} form the form to initialize.
+ */
+ _initDetailForm(form) {
+ if (form instanceof Form) {
+ form.setModal(false);
+ }
+ if (!form.displayParent && form.setDisplayParent) {
+ form.setDisplayParent(this.getOutline());
+ }
+ if (form instanceof TileOverviewForm) {
+ form.setPage(this);
+ }
+ }
+
+ /**
+ * Override this function to destroy the internal (detail) form.
+ * @param {Form} form the form to destroy.
*/
- _initTable(table) {
+ _destroyDetailForm(form) {
+ if (form instanceof TileOverviewForm) {
+ form.setPage(null);
+ }
+ if (form.owner === this.getOutline()) {
+ // in Scout classic the owner is not an outline but the NullWidget.
+ // Then the destroy is controlled by the backend
+ form.destroy();
+ }
+ }
+
+ /**
+ * Override this function to initialize the internal (detail) table.
+ * Default impl. delegates filter events to the outline mediator.
+ * @param {Table} table The table to initialize.
+ */
+ _initDetailTable(table) {
table.menuBar.setPosition(MenuBar.Position.TOP);
- table.on('filter', this._onTableFilter.bind(this));
+ table.on('filter', this._tableFilterHandler);
if (this.drillDownOnRowClick) {
- table.on('rowClick', this._onTableRowClick.bind(this));
+ table.on('rowClick', this._tableRowClickHandler);
table.setMultiSelect(false);
}
+ table.setTableStatusVisible(this.tableStatusVisible);
}
- _ensureDetailForm() {
- if (this.detailForm) {
- return;
- }
- let form = this.createDetailForm();
- if (form && !form.displayParent) {
- form.setDisplayParent(this.getOutline());
+ /**
+ * Override this function to destroy the internal (detail) table.
+ * @param {Table} table the table to destroy.
+ */
+ _destroyDetailTable(table) {
+ table.off('filter', this._tableFilterHandler);
+ table.off('rowClick', this._tableRowClickHandler);
+ if (table.owner === this.getOutline()) {
+ // in Scout classic the owner is not an outline but the NullWidget.
+ // Then the destroy is controlled by the backend
+ table.destroy();
}
- this.setDetailForm(form);
}
/**
@@ -167,7 +268,8 @@ export default class Page extends TreeNode {
// see Java: AbstractPage#pageActivatedNotify
activate() {
- this._ensureDetailForm();
+ this.ensureDetailTable();
+ this.ensureDetailForm();
}
// see Java: AbstractPage#pageDeactivatedNotify
@@ -197,22 +299,50 @@ export default class Page extends TreeNode {
return row.page;
}
+ /**
+ * @param {Form} form The new form
+ */
setDetailForm(form) {
- this.detailForm = form;
- if (this.detailForm) {
- this.detailForm.setModal(false);
+ if (form === this.detailForm) {
+ return;
}
- if (this.detailForm instanceof scout.TileOverviewForm) {
- this.detailForm.setPage(this);
+ this._setDetailForm(form);
+ }
+
+ _setDetailForm(form) {
+ let oldDetailForm = this.detailForm;
+ if (oldDetailForm !== form && oldDetailForm instanceof Widget) {
+ // must be a widget to be destroyed. At startup in Scout Classic it might be a string (the widget id)
+ this._destroyDetailForm(oldDetailForm);
}
+ this.detailForm = form;
+ if (form) {
+ this._initDetailForm(form);
+ }
+ this.triggerPropertyChange('detailForm', oldDetailForm, form);
}
+ /**
+ * @param {Table} table The new table
+ */
setDetailTable(table) {
- if (table) {
- this._initTable(table);
- table.setTableStatusVisible(this.tableStatusVisible);
+ if (table === this.detailTable) {
+ return;
+ }
+ this._setDetailTable(table);
+ }
+
+ _setDetailTable(table) {
+ let oldDetailTable = this.detailTable;
+ if (oldDetailTable !== table && oldDetailTable instanceof Widget) {
+ // must be a widget to be destroyed. At startup in Scout Classic it might be a string (the widget id)
+ this._destroyDetailTable(oldDetailTable);
}
this.detailTable = table;
+ if (table) {
+ this._initDetailTable(table);
+ }
+ this.triggerPropertyChange('detailTable', oldDetailTable, table);
}
/**
@@ -306,4 +436,36 @@ export default class Page extends TreeNode {
this.getOutline().selectNode(drillNode);
this.detailTable.deselectRow(row);
}
+
+ /**
+ * Triggers a property change for a single property.
+ */
+ triggerPropertyChange(propertyName, oldValue, newValue) {
+ scout.assertParameter('propertyName', propertyName);
+ let event = new Event({
+ propertyName: propertyName,
+ oldValue: oldValue,
+ newValue: newValue
+ });
+ this.trigger('propertyChange', event);
+ return event;
+ }
+
+ trigger(type, event) {
+ event = event || {};
+ event.source = this;
+ this.events.trigger(type, event);
+ }
+
+ one(type, func) {
+ this.events.one(type, func);
+ }
+
+ on(type, func) {
+ return this.events.on(type, func);
+ }
+
+ off(type, func) {
+ this.events.off(type, func);
+ }
}
diff --git a/eclipse-scout-core/src/desktop/outline/pages/PageWithNodes.js b/eclipse-scout-core/src/desktop/outline/pages/PageWithNodes.js
index 121678aa3d..eb4c7faf38 100644
--- a/eclipse-scout-core/src/desktop/outline/pages/PageWithNodes.js
+++ b/eclipse-scout-core/src/desktop/outline/pages/PageWithNodes.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017 BSI Business Systems Integration AG.
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -26,7 +26,7 @@ export default class PageWithNodes extends Page {
/**
* @override Page.js
*/
- _createTable() {
+ _createDetailTable() {
let nodeColumn = scout.create('Column', {
id: 'NodeColumn',
session: this.session
@@ -49,6 +49,9 @@ export default class PageWithNodes extends Page {
_rebuildDetailTable(childPages) {
let table = this.detailTable;
+ if (!table) {
+ return;
+ }
this._unlinkAllTableRows(table.rows);
table.deleteAllRows();
let rows = this._createTableRowsForChildPages(childPages);
diff --git a/eclipse-scout-core/src/desktop/outline/pages/PageWithTable.js b/eclipse-scout-core/src/desktop/outline/pages/PageWithTable.js
index 35260040b1..504bd6e58d 100644
--- a/eclipse-scout-core/src/desktop/outline/pages/PageWithTable.js
+++ b/eclipse-scout-core/src/desktop/outline/pages/PageWithTable.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017 BSI Business Systems Integration AG.
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,22 +22,42 @@ export default class PageWithTable extends Page {
this.nodeType = Page.NodeType.TABLE;
this.alwaysCreateChildPage = false;
+
+ this._tableRowDeleteHandler = this._onTableRowsDeleted.bind(this);
+ this._tableRowInsertHandler = this._onTableRowsInserted.bind(this);
+ this._tableRowUpdateHandler = this._onTableRowsUpdated.bind(this);
+ this._tableRowActionHandler = this._onTableRowAction.bind(this);
+ this._tableRowOrderChangeHandler = this._onTableRowOrderChanged.bind(this);
+ this._tableDataLoadHandler = this.loadTableData.bind(this);
}
/**
* @override Page
*/
- _initTable(table) {
- super._initTable(table);
- table.on('rowsDeleted allRowsDeleted', this._onTableRowsDeleted.bind(this));
- table.on('rowsInserted', this._onTableRowsInserted.bind(this));
- table.on('rowsUpdated', this._onTableRowsUpdated.bind(this));
- table.on('rowAction', this._onTableRowAction.bind(this));
- table.on('rowOrderChanged', this._onTableRowOrderChanged.bind(this));
- table.on('reload', this.loadTableData.bind(this));
+ _initDetailTable(table) {
+ super._initDetailTable(table);
+ table.on('rowsDeleted allRowsDeleted', this._tableRowDeleteHandler);
+ table.on('rowsInserted', this._tableRowInsertHandler);
+ table.on('rowsUpdated', this._tableRowUpdateHandler);
+ table.on('rowAction', this._tableRowActionHandler);
+ table.on('rowOrderChanged', this._tableRowOrderChangeHandler);
+ table.on('reload', this._tableDataLoadHandler);
table.hasReloadHandler = true;
}
+ /**
+ * @override Page
+ */
+ _destroyDetailTable(table) {
+ table.off('rowsDeleted allRowsDeleted', this._tableRowDeleteHandler);
+ table.off('rowsInserted', this._tableRowInsertHandler);
+ table.off('rowsUpdated', this._tableRowUpdateHandler);
+ table.off('rowAction', this._tableRowActionHandler);
+ table.off('rowOrderChanged', this._tableRowOrderChangeHandler);
+ table.off('reload', this._tableDataLoadHandler);
+ super._destroyDetailTable(table);
+ }
+
_onTableRowsDeleted(event) {
if (this.leaf) { // when page is a leaf we do nothing at all
return;
@@ -135,6 +155,7 @@ export default class PageWithTable extends Page {
* @returns {$.Deferred}
*/
loadTableData() {
+ this.ensureDetailTable();
this.detailTable.deleteAllRows();
this.detailTable.setLoading(true);
return this._loadTableData(this._createSearchFilter())
diff --git a/eclipse-scout-core/src/widget/Widget.js b/eclipse-scout-core/src/widget/Widget.js
index bf012174c7..63096d040b 100644
--- a/eclipse-scout-core/src/widget/Widget.js
+++ b/eclipse-scout-core/src/widget/Widget.js
@@ -1388,8 +1388,7 @@ export default class Widget {
}
/**
- * Triggers a property change for a single property. The event is only triggered when
- * old and new value are the same.
+ * Triggers a property change for a single property.
*/
triggerPropertyChange(propertyName, oldValue, newValue) {
scout.assertParameter('propertyName', propertyName);
diff --git a/eclipse-scout-core/test/desktop/outline/pages/PageSpec.js b/eclipse-scout-core/test/desktop/outline/pages/PageSpec.js
new file mode 100644
index 0000000000..da835d99c6
--- /dev/null
+++ b/eclipse-scout-core/test/desktop/outline/pages/PageSpec.js
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BSI Business Systems Integration AG - initial API and implementation
+ */
+import {Form, Page, PageWithTable, scout, Table, Widget} from '../../../../src';
+import {OutlineSpecHelper} from '../../../../src/testing';
+
+describe('Page', () => {
+
+ let session;
+ /** @type {Outline} */
+ let outline;
+
+ beforeEach(() => {
+ setFixtures(sandbox());
+ session = sandboxSession();
+ outline = new OutlineSpecHelper(session).createOutline();
+ });
+
+ it('detailTable and detailForm are created lazily on page activation when created as object', () => {
+ // test with object
+ let page = createAndInsertPage({
+ objectType: 'Table'
+ }, {
+ objectType: 'Form'
+ });
+ expect(page.detailTable).toBeFalsy();
+ expect(page.detailForm).toBeFalsy();
+ expectListenersToBeExecuted(0, page); // not created yet
+ outline.selectNode(page); // page is activated
+ expect(page.detailTable).toBeInstanceOf(Table);
+ expect(page.detailForm).toBeInstanceOf(Widget);
+ expectListenersToBeExecuted(2, page); // both listeners executed
+ });
+
+ it('detailTable and detailForm are initialized when passed as widget', () => {
+ // if form or table is directly provided as widget: it is available right from the start
+ let page = createAndInsertPage(
+ scout.create('Table', {parent: outline}),
+ scout.create('Form', {parent: outline}));
+ expect(page.detailTable).toBeInstanceOf(Table);
+ expect(page.detailForm).toBeInstanceOf(Widget);
+ expectListenersToBeExecuted(2, page); // both listeners already executed without selecting the page
+ });
+
+ it('detailTable and detailForm are destroyed when overwritten', () => {
+ let page = createAndInsertPage({
+ objectType: 'Table'
+ }, {
+ objectType: 'Form'
+ });
+ outline.selectNode(page);
+ expect(page.detailTable).toBeInstanceOf(Table);
+ expect(page.detailForm).toBeInstanceOf(Widget);
+
+ let oldForm = page.detailForm;
+ let newForm = scout.create('Form', {parent: outline});
+ page.setDetailForm(newForm);
+ expect(oldForm.destroyed).toBe(true);
+ expect(newForm.destroyed).toBe(false);
+
+ let oldTable = page.detailTable;
+ let newTable = scout.create('Table', {parent: outline});
+ page.setDetailTable(newTable);
+ expect(oldTable.destroyed).toBe(true);
+ expect(newTable.destroyed).toBe(false);
+ });
+
+ function createAndInsertPage(detailTable, detailForm) {
+ let page = new PageWithLazyCreationCounter();
+ page.on('propertyChange:detailForm', e => e.source.numFormCreated++);
+ page.on('propertyChange:detailTable', e => e.source.numTableCreated++);
+ page.init({
+ parent: outline,
+ detailTable: detailTable,
+ detailForm: detailForm
+ });
+ outline.insertNodes([page], null);
+ return page;
+ }
+
+ function expectListenersToBeExecuted(expectation, page) {
+ expect(page.numTableCreated).toBe(expectation);
+ expect(page.numFormCreated).toBe(expectation);
+ }
+
+ class PageWithLazyCreationCounter extends PageWithTable {
+
+ constructor() {
+ super();
+ this.numTableCreated = 0;
+ this.numFormCreated = 0;
+ }
+
+ _initDetailForm(form) {
+ super._initDetailForm(form);
+ expect(form).toBeInstanceOf(Form);
+ this.numFormCreated++;
+ }
+
+ _initDetailTable(table) {
+ super._initDetailTable(table);
+ expect(table).toBeInstanceOf(Table);
+ this.numTableCreated++;
+ }
+ }
+});
diff --git a/eclipse-scout-core/test/desktop/outline/pages/PageWithTableSpec.js b/eclipse-scout-core/test/desktop/outline/pages/PageWithTableSpec.js
index 9cf6991609..6bb553f038 100644
--- a/eclipse-scout-core/test/desktop/outline/pages/PageWithTableSpec.js
+++ b/eclipse-scout-core/test/desktop/outline/pages/PageWithTableSpec.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2020 BSI Business Systems Integration AG.
+ * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -35,6 +35,7 @@ describe('PageWithTable', () => {
});
outline.insertNodes([page], null);
outline.render();
+ outline.selectNode(page);
page.detailTable.render();
jasmine.clock().install();
diff --git a/scout-hellojs-app/src/main/resources/archetype-resources/__rootArtifactId__.ui/src/main/js/person/PersonTablePage.js b/scout-hellojs-app/src/main/resources/archetype-resources/__rootArtifactId__.ui/src/main/js/person/PersonTablePage.js
index d16b1c16e8..72b7401087 100644
--- a/scout-hellojs-app/src/main/resources/archetype-resources/__rootArtifactId__.ui/src/main/js/person/PersonTablePage.js
+++ b/scout-hellojs-app/src/main/resources/archetype-resources/__rootArtifactId__.ui/src/main/js/person/PersonTablePage.js
@@ -18,6 +18,10 @@ export default class PersonTablePage extends PageWithTable {
_init(model) {
let m = ${symbol_dollar}.extend({}, this._jsonModel(), model);
super._init(m);
+ }
+
+ _initDetailTable(table) {
+ super._initDetailTable(table);
this._initListeners();
}
@@ -82,10 +86,9 @@ export default class PersonTablePage extends PageWithTable {
_createPersonForm() {
let outline = this.getOutline();
- let personForm = scout.create('${simpleArtifactName}.PersonForm', {
+ return scout.create('${simpleArtifactName}.PersonForm', {
parent: outline
});
- return personForm;
}
_onEditPersonMenuAction(event) {

Back to the top