Panel

About Panel

The Panel component is a component that allows you to group two or more components together and arrange them in a desired format.

It is similar to the Div component in that it displays multiple components within a component, but the Panel component is not a container component. A container component has subordinate components,whereas the Panel component only serves to logically group components of equal hierarchy.

If you look at the code for the Div component, you can see that the Button component is placed under the Div component layout. If you want to access the Button00 component, for example, you will have to go through the Div component because you cannot access it directly.

<Div id="Div00">
	<Layouts>
		<Layout>
			<Button id="Button00" left="10" top="10" width="120" height="50"/>
			<Button id="Button01" left="150" top="10" width="120" height="50"/>
		</Layout>
	</Layouts>
</Div>

However, the components associated with the Panel component are placed in the same hierarchy as the Panel component, under the Form object layout. The Panel component is simply connecting to the Button component as PanelItem.

<Form>
	<Layouts>
		<Layout>
			<Panel>
				<Contents>
					<PanelItem id="PanelItem00" componentid="Button00"/>
					<PanelItem id="PanelItem02" componentid="Button01"/>
				</Contents>
			</Panel>
			<Button id="Button00"/>
			<Button id="Button01"/>
		</Layout>
	</Layouts>
</Form>

Use the following approach to access the Button component placed in the Div component and the Button component connected to the Panel component:

this.Div00;
this.Div00.form.Button00;

this.Panel00;
this.Button00;

In the Outlineview window, they appear to be hierarchically separated, just like the Div component, but this is to facilitate the work process, and the actual hierarchy is different for the Div component and the Panel component.

Adding Items to the Panel Component

There are three ways to add items to the Panel component.

Group by Panel

Place the components on the page, select the components you want to group together, and then select [Group by Panel] in the Context menu.

To cancel the groupiing, select the Panel component and select [Ungroup Panels] in the Context menu.

Dragging and placing components

This is similar to placing a component inside a Div component. However, you cannot specify coordinates for a Panel component, and you can only choose one of the following formats: horizontal, vertical, or table.

Setting the Item Property of a Panel Component

You can selecting a Panel component and set the items properties in the properties pane.

Grouping Components

You can use the Panel component to group two or more components together and make them behave like a single component.

Example

When you resize a Div component, the components grouped together with a Panel component will be treated as a single component.

sample_panel_01.xfdl

Core features used in the example

flexwrap

When components are placed beyond the Layout container area, line breaks will be handled on a per-component basis. In the following examples, we'll examine the difference between individual components and components grouped using a Panel component.

How to implement an example

1

Place a Div component on the page.

2

Change the property values of the Div component as shown below.

type: "horizontal"

flexwrap: "wrap"

verticalgap: 5

3

Inside the Div component, place a Static component and an Edit component as shown below.

Make the width of the Static component 100 and the Edit component 120 to make their widths different.

4

Place a Button component next to the Div component.

5

Add an onclick event handler function to the Button component as shown below.

When the Button component is clicked, halve the size of the Div component and adjust its height to fit the content by using the fittocontents property.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.Div00.width = this.Div00.width * 0.5;
	this.Div00.fittocontents = "height";
	this.resetScroll();
};

6

Run QuickView (Ctrl + F6) and click the Button component to see how the placement of the components changes.

As the Div component decreases in size, the Static and Edit components will no longer appear on the same line and will be each placed on different lines.

7

Back in Nexacro Studio, select the Static and Edit components and choose [Group by Panel] from the context menu.

When viewed in Outlineview, it should look as follows. Static00 and Edit00 were grouped together with Panel00 and Static01 and Edit01 with Panel01.

8

Run QuickView (Ctrl + F6) and click on the Button component to see how the placement of the components changes.

You'll notice that line breaks are handled on per-Panel component basis, not by the Static or Edit components.

Creating a Mega Menu

A Mega Menu is a method that displays sub-items (or all sub-items) related to the selected top-level menu item in a sitemap-like layout. This example shows how to dynamically place and display top-level and sub-menu items when the screen loads. It also demonstrates how to reconfigure the menu items based on user permissions.

This example partially references the demo on the Nexacro demo site.

https://demo.tobesoft.com/?menu_id=2008

Example

When a top-level menu is selected, its sub-menu items are displayed. Depending on the checked state of the "Admin User" item, the "Admin" menu is either excluded or included.

sample_panel_02.xfdl

Core features used in the example

setFluidLayoutProperty

This is a method used to dynamically configure layout-related properties in a Fluid Layout. As of the current version, only the tabletemplate property can be set.

How to implement an example

1

Place Div and Static components on the screen.

The Div component is the area where the menu items will be displayed, and the Static component is the area that shows information about the selected menu. Normally, selecting a menu item moves to a corresponding screen, but in this example, only basic information is displayed.

2

Set the type property of the Div component to "table", and set the background property to "lightgray".

3

Set the visible property of the Div component (divSubMenu) used to display the sub-menu to false.

4

Add a Dataset object and configure the data as shown below.

Items with a MENU_LVL column value of 1 are displayed as top-level menus, and those with a value of 2 are displayed as sub-menus. For the full dataset, refer to the sample code.

5

Add an onload event handler function to the Form and write the code as follows.

In the initializeMegaMenu function, the data from the Dataset object is checked and the menu items are arranged. The following behaviors are handled.

const LEFT = 0;
const TOP = 0;
const FULL_WIDTH = "100%"
const FULL_HEIGHT = "100%"
const MENU_HEIGHT = 30;	

this.sample_panel_02_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
	this.initializeMegaMenu();
};

this.initializeMegaMenu = function (adminFilter="")
{
	// Clear previously created menu items
	this.fnRemoveComponent(this.divUpMenu);
	this.fnRemoveComponent(this.divSubMenu);
	
	// Filter Dataset object to retrieve items for the top-level menu
	this.dsMegaMenu.filter("MENU_LVL == 1"+adminFilter);
	const MENU_COUNT = this.dsMegaMenu.rowcount;
	
	const TABLETEMPLATE_VALUE = this.generateMenuString(MENU_COUNT);
	// Set the tabletemplate property of the Div component according to the number of menu items
	this.divUpMenu.form.setFluidLayoutProperty("default", "tabletemplate", TABLETEMPLATE_VALUE);
	this.divSubMenu.form.setFluidLayoutProperty("default", "tabletemplate", TABLETEMPLATE_VALUE);
	
	let subMenuMaxCount = 0;
	
	for (let i=0;i<MENU_COUNT;i++) {
		let menuCd = this.dsMegaMenu.getColumn(i, "MENU_CD");
		let menuNm = this.dsMegaMenu.getColumn(i, "MENU_NM");
		
		// Create Static component for top-level menu
		this.createStatic("sta_"+menuCd, FULL_HEIGHT, menuNm, i, "center", this.divUpMenu);
		
		// Create Panel component to handle sub-menu items
		// Div components cannot set type property values dynamically, so Panel is used instead
		let subMenuPanel = this.createPanel("panel_"+menuCd, FULL_HEIGHT, i, this.divSubMenu);
		
		// Create Static component for sub-menu
		let subMenuTitleStatic = this.createStatic("sta_sub_"+menuCd, MENU_HEIGHT, menuNm, i, "center", this.divSubMenu);
		subMenuTitleStatic.color = "red";
		subMenuPanel.addItem(subMenuTitleStatic.name, subMenuTitleStatic.id);		
		
		this.dsMegaMenu.filter("UP_MENU_CD == '" + menuCd + "'");
		
		let nSubCount = this.dsMegaMenu.rowcount;
		if(nSubCount > subMenuMaxCount) subMenuMaxCount = nSubCount;
		
		for (let j=0;j<nSubCount;j++) {
			let subMenuCd = this.dsMegaMenu.getColumn(j, "MENU_CD");
			let subMenuNm = this.dsMegaMenu.getColumn(j, "MENU_NM");
			
			let objSubMenuSta = this.createStatic("subSta_"+subMenuCd, MENU_HEIGHT, subMenuNm, i, "left", this.divSubMenu);
			subMenuPanel.addItem(objSubMenuSta.name, objSubMenuSta.id);
		}
		this.dsMegaMenu.filter("MENU_LVL == 1"+adminFilter);
	}
	this.divSubMenu.height = (subMenuMaxCount+1)*MENU_HEIGHT;
};

// Create a Static component as a menu item and add it as a child of the target Div.
this.createStatic = function (id, height, text, tablecellindex, textAlign, targetDiv) {
    let objStatic = new Static();
    objStatic.init(id, LEFT, TOP, FULL_WIDTH, height);
    objStatic.text = text;
    objStatic.tablecellarea = "0 / "+tablecellindex;
    objStatic.textAlign = textAlign;
	objStatic.addEventHandler("onclick", this.fnMenuOnClick, this);
	targetDiv.addChild(objStatic.name, objStatic);
	objStatic.show();	
    return objStatic;
};

// Create a Panel component to place sub-menu items and add it as a child of the target Div
this.createPanel = function (id, height, tablecellindex, targetDiv) {
    let objPanel = new Panel();
    objPanel.init(id, LEFT, TOP, FULL_WIDTH, height);
    objPanel.tablecellarea = "0 / "+tablecellindex;;
	objPanel.type = "vertical";
	targetDiv.addChild(objPanel.name, objPanel);
	objPanel.show();	
    return objPanel;
};

// Generate the string to be used as the tabletemplate property value based on the number of menu items
this.generateMenuString = function(menuCount) {
    const repeatedString = "1* ".repeat(menuCount).trim();
    return "1* / "+repeatedString;
}

If you add lines to the running screen and check, you’ll see that both the top-level menu and sub-menu each have five columns, and the sub-menu’s Panel component is set to allow vertical stacking of components.

6

Add an event handler function to handle the menu click event.

this.toggleSubMenuVisibility = function () {
    this.divSubMenu.visible = !this.divSubMenu.visible;
};

this.fnMenuOnClick = function(obj:nexacro.Static,e:nexacro.ClickEventInfo)
{
	this.toggleSubMenuVisibility();
	this.staMenuClick.text = obj.text;
}

7

Add a CheckBox component to the screen and an onchanged event handler function.

this.fnRemoveComponent = function(targetDiv) {
    if (targetDiv.form.components.length > 0) {
        for (let i = targetDiv.form.components.length - 1; i >= 0; i--) {
            let component = targetDiv.form.components[i];
            targetDiv.removeChild(component.name);
            component.destroy();
        }
    }
};

this.ckAdminUser_onchanged = function(obj:nexacro.CheckBox,e:nexacro.CheckBoxChangedEventInfo)
{
	if(e.postvalue)
		this.initializeMegaMenu();
	else
		this.initializeMegaMenu(" && ADMIN_MENU != 1");
};

8

Run QuickView (Ctrl + F6) and check that the menu items are displayed.