Handle selection events in an Oracle JET virtual DOM app
Introduction
In your Oracle JavaScript Extension Toolkit (Oracle JET) virtual DOM app, you can use a combination of resources from Preact, including state, props, and hooks, to create change listeners and event handlers that respond to selection and deselection in Oracle JET List View components. When the user selects an activity or activity item in the app’s master or detail list views, the change listener triggers your event handler, which creates the Oracle JET data provider object that populates the List View components in the Activity and Activity Item Containers.
In the parent container components, implement a conditional rendering of the child components so that if certain selected attributes of the Oracle JET List View components are not empty, then a variable is set to true, and the view renders the databound detail list. If the selected attribute is empty due to a deselection event, then the variable is set to false, and the child components render with no detail view.
Objectives
In this tutorial, you will update the user interface of an Oracle JET virtual DOM app so that you can display master-detail data that responds to Oracle JET List View component selection events.
Prerequisites
- A development environment set up to create Oracle JET virtual DOM apps that includes an installation of Node.js
- Completion of the previous tutorial in this learning path, Create the Detail View in an Oracle JET Virtual DOM App
- The completed app jet-virtual-dom-app-temp.zip optionally downloaded
Task 1: Modify Parent Container 1 for Selection
-
Navigate to the
JET-Virtual-DOM-app/src/componentsdirectory and open theParentContainer1.tsxfile in an editor. -
Add an
importstatement for theuseStatehook to the top of the file.import { useState } from 'preact/hooks'; -
Create an
Itemtype alias and anINIT_SELECTEDACTIVITYvariable.type Item = { id: number; name: string; short_desc?: string; price?: number; quantity?: number; quantity_shipped?: number; quantity_instock?: number; activity_id?: number; image?: string; }; let INIT_SELECTEDACTIVITY: Item | null = null; -
Before the
returnstatement in theParentContainer1function, add the following code.const [selectedActivity, setSelectedActivity] = useState(INIT_SELECTEDACTIVITY); const showActivityItems = () => { return selectedActivity != null ? true : false; }; const activityChangedHandler = (value: Item) => { setSelectedActivity(value); }; -
Add the
onActivityChangedattribute to theActivityContainerelement, and replace theParentContainer2element with a pair of conditional statements used either to display theParentContainer2element with aselectedActivityprop value sourced from theActivityContainercomponent, or to display a header with instructions to select an activity. Also delete theoj-bg-warning-20andoj-panelstyle classes from thedivelement to remove the yellow background color and border from the container.return ( <div id="parentContainer1" class="oj-flex oj-flex-init"> <ActivityContainer data={activityDataProvider} onActivityChanged={activityChangedHandler} /> {showActivityItems() && <ParentContainer2 activity={selectedActivity} />} {!showActivityItems() && ( <h4 class="oj-typography-subheading-sm">Select activity to view items</h4> )} </div> );Save the file. Your code should look similar to
parent-container1-1-tsx.txt
Task 2: Modify the Activity Container for Selection
-
Navigate to the
JET-Virtual-DOM-app/src/components/Activitydirectory and open theActivityContainer.tsxfile in an editor. -
Add the following
importstatements to the top of the file.import { KeySetImpl, KeySet } from 'ojs/ojkeyset'; import { useMemo } from 'preact/hooks'; -
Add the
onActivityChangedproperty to thePropstype alias. Also create anItemtype alias.type Props = { data?: MutableArrayDataProvider<Activity['id'], Activity>; value?: string; onActivityChanged: (value: Item) => void; }; type Item = { id: number; name: string; short_desc?: string; price?: number; quantity?: number; quantity_shipped?: number; quantity_instock?: number; activity_id?: number; image?: string; }; -
Before the
returnstatement in theActivityContainerfunction, add the following code.const selectedActivityChanged = ( event: ojListView.firstSelectedItemChanged<Item['id'], Item> ) => { props.onActivityChanged(event.detail.value.data); }; const activityValue = useMemo(() => { return new KeySetImpl([props.value]) as KeySet<Activity['name']>; }, [props.value]); -
Add the
selectedandonfirstSelectedItemChangedattributes to the Oracle JET List View component. Also delete theoj-bg-info-30from thedivelement to remove the blue background color from the container.selected = { activityValue }; onfirstSelectedItemChanged = { selectedActivityChanged };Save the file. Your code should look similar to
activity-container-1-tsx.txt.
Task 3: Modify Parent Container 2 for Selection
-
Navigate to the
JET-Virtual-DOM-app/src/componentsdirectory and open theParentContainer2.tsxfile in an editor. -
Add an
importstatement for the following Preact hooks to the top of the file.import { useState, useEffect, useCallback } from 'preact/hooks'; -
Add a
Propstype alias.type Props = { activity: Item | null; }; -
Rename
const activityItemDPasconst INIT_DATAPROVIDERand delete the variableconst specificItem. -
Add
propsto theParentContainer2function definitionconst ParentContainer2 = (props: Props) => { -
Add state and Preact hooks before the function’s
returnstatement.const [selectedItemVal, setSelectedItemVal] = useState<Item | null>(null); const [activityItemDP, setactivityItemDP] = useState(INIT_DATAPROVIDER); const activityItemChangeHandler = useCallback( (item: Item) => { setSelectedItemVal(item); }, [selectedItemVal] ); const showItems = useCallback(() => { return selectedItemVal === null ? false : true; }, [selectedItemVal]); -
Add a
useEffecthook before thereturnstatement.useEffect(() => { let actID = props.activity.id - 1; let activityItemsArray = activityData[actID].items; setactivityItemDP( new MutableArrayDataProvider<ActivityItem['id'], ActivityItem>(activityItemsArray, { keyAttributes: 'id', }) ); }, [props.activity]); -
Add the
selectedActivityandonItemChangeddata attributes to theActivityItemContainerelement. Replace theItemDetailContainerelement with a pair of conditional statements to either display theItemDetailContainerwith its selected activity item value or display a header with instructions to select an activity item. Also delete theoj-panelandoj-bg-danger-30style classes from thedivelement to remove the red background color and border from the container.<div id="parentContainer2" class="oj-flex oj-flex-item oj-lg-padding-6x-horizontal oj-md-8 oj-sm-12"> <ActivityItemContainer selectedActivity={props.activity} data={activityItemDP} onItemChanged={activityItemChangeHandler} /> {showItems() && <ItemDetailContainer item={selectedItemVal} />} {!showItems() && ( <h4 class="oj-typography-subheading-sm">Select activity item to see details</h4> )} </div>Your code should look similar to
parent-container2-1-tsx.txt
Task 4: Modify the Activity Item Container for Selection
-
Navigate to the
JET-Virtual-DOM-app/src/components/ActivityItemdirectory and open theActivityItemContainer.tsxfile in an editor. -
Add an
importstatement for the following Preact hooks to the top of the file.import { useState, useCallback } from 'preact/hooks'; -
Replace the
Propstype alias.type Props = { data?: MutableArrayDataProvider<ActivityItem['id'], ActivityItem>; selectedActivity: Item | null; onItemChanged: (item: Item) => void; }; -
Add a
DEFAULT_ACTIVITY_ITEM_STATEvariable.const DEFAULT_ACTIVITY_ITEM_STATE: Partial<Item> = {}; -
Add the following code before the
returnstatement in theActivityItemContainerfunction definition.// new code const activityItemDataProvider = props.data; const [activityItemValue, setActivityItemValue] = useState(DEFAULT_ACTIVITY_ITEM_STATE); const [itemData, setItemData] = useState<Item>(props.selectedActivity!); const selectedActivityItemChanged = useCallback( (event: ojListView.firstSelectedItemChanged<Item['id'], Item>) => { let tempItem = event.detail.value.data; props.onItemChanged(tempItem); setActivityItemValue(tempItem); setItemData(tempItem); }, [activityItemValue] ); -
In the Oracle JET List View element, add an
onFirstSelectedItemChangedattribute and replace thedataattribute. Also delete theoj-bg-success-20style class from thedivelement whereid="activityItemsContainer"to remove the green background color from the container.<div id="activityItemsContainer" class="oj-flex-item oj-sm-padding-4x-start oj-md-6 oj-sm-12"> <div id="container"> <h3>Activity Items</h3> <oj-list-view id="activitiesList" class="item-display" aria-labelledby="activitiesHeader" data={activityItemDataProvider} gridlines={gridlinesItemVisible} selectionMode="single" onfirstSelectedItemChanged={selectedActivityItemChanged} scrollPolicy="loadMoreOnScroll" scrollPolicyOptions={scrollPolicyOpts}> <template slot="itemTemplate" render={listItemRenderer}></template> </oj-list-view>Save the file. Your code should look similar to
activity-item-container-tsx.txt -
Navigate to the
JET-Virtual-DOM-app/src/components/ItemDetaildirectory and open theItemDetailContainer.tsxfile in an editor. -
In the
returnstatement of theItemDetailContainerfunction, delete theoj-bg-neutral-30style class from thedivelement to remove the gray background color from the container. Save the file.
Task 5: Test Selection Events in the Virtual DOM App
-
In the terminal window, change to the
JET-Virtual-DOM-appdirectory and run the virtual DOM app.npx ojet serve -
In the virtual DOM app, click the Baseball activity.
The Activities list selection triggers the
selectedActivityChangedevent handler. The virtual DOM app renders the activity item data of the selected activity.
-
In the Activity Items list, click the SureCatch Baseball Glove.
The Activity Items list selection triggers the
selectedActivityItemChangedevent handler. The virtual DOM app renders the Item Details Container with the data from the selected activity item.
-
In the Activity Items list, press Ctrl and click SureCatch Baseball Glove to deselect it.
The Activity Items list deselection triggers the
selectedItemChangedevent handler. The Item Detail Container is hidden.
-
Press Ctrl+Shift+I or right-click the page and select Inspect to bring up the page view in the developer tools.
-
In the Chrome DevTools toolbar, click
to switch to the device mode. -
From the Dimensions dropdown menu in the screen emulator, select a device with a small screen size, such as the Pixel 5, to verify the content changes.

-
Close the browser window or tab that displays your running virtual DOM app.
-
In the terminal window, press Ctrl+C, and if prompted, enter
yto exit the Oracle JET tooling batch job.
Task 6: (Optional) Run a Virtual DOM App from a Restored App
If you want to run the completed Oracle JET virtual DOM app from the supplied code, you can restore the virtual DOM app from the downloaded archive file. To work with a stripped and zipped Oracle JET virtual DOM app, you must restore project dependencies, including Oracle JET tooling and the required libraries and modules, within the extracted virtual DOM app.
-
Download the
jet-virtual-dom-app-temp.zipfile, rename it asJET-Virtual-DOM-app.zip, and extract the contents to theJET-Virtual-DOM-appdirectory. -
In the terminal window, navigate to the
JET-Virtual-DOM-appdirectory and restore the Oracle JET virtual DOM app.npm install -
Wait for confirmation.
Success: Restore completeThe virtual DOM app is ready to run.
-
Run the virtual DOM app and test it in the browser.
npx ojet serve -
Close the browser window or tab that displays your running virtual DOM app.
-
In the terminal window, press Ctrl+C, and if prompted, enter
yto exit the Oracle JET tooling batch job.
Next Step
This tutorial concludes the module Master Detail Views in Oracle JET in this learning path on building virtual DOM web apps.
- Create the Master View in an Oracle JET Virtual DOM App
- Create the Detail View in an Oracle JET Virtual DOM App
- Handle Selection Events in an Oracle JET Virtual DOM App
You can proceed to the next tutorial in the learning path, Fetch Data from the REST API in Oracle JET, in the module CRUD Operations Using a REST Service.
You can also return to the virtual DOM learning path’s main page to access all the modules on building virtual DOM apps.
More Learning Resources
Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.
For product documentation, visit Oracle Help Center.
Handle selection events in an Oracle JET virtual DOM app
F72827-04