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/components
directory and open theParentContainer1.tsx
file in an editor. -
Add an
import
statement for theuseState
hook to the top of the file.import { useState } from "preact/hooks";
-
Create an
Item
type alias and anINIT_SELECTEDACTIVITY
variable.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
return
statement in theParentContainer1
function, 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
onActivityChanged
attribute to theActivityContainer
element, and replace theParentContainer2
element with a pair of conditional statements used either to display theParentContainer2
element with aselectedActivity
prop value sourced from theActivityContainer
component, or to display a header with instructions to select an activity. Also delete theoj-bg-warning-20
andoj-panel
style classes from thediv
element 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/Activity
directory and open theActivityContainer.tsx
file in an editor. -
Add the following
import
statements to the top of the file.import { KeySetImpl, KeySet } from "ojs/ojkeyset"; import { useMemo } from "preact/hooks";
-
Add the
onActivityChanged
property to theProps
type alias. Also create anItem
type 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
return
statement in theActivityContainer
function, 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
selected
andonfirstSelectedItemChanged
attributes to the Oracle JET List View component. Also delete theoj-bg-info-30
from thediv
element 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/components
directory and open theParentContainer2.tsx
file in an editor. -
Add an
import
statement for the following Preact hooks to the top of the file.import { useState, useEffect, useCallback } from "preact/hooks";
-
Add a
Props
type alias.type Props = { activity: Item | null; };
-
Rename
const activityItemDP
asconst INIT_DATAPROVIDER
and delete the variableconst specificItem
. -
Add
props
to theParentContainer2
function definitionconst ParentContainer2 = (props: Props) => {
-
Add state and Preact hooks before the function’s
return
statement.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
useEffect
hook before thereturn
statement.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
selectedActivity
andonItemChanged
data attributes to theActivityItemContainer
element. Replace theItemDetailContainer
element with a pair of conditional statements to either display theItemDetailContainer
with its selected activity item value or display a header with instructions to select an activity item. Also delete theoj-panel
andoj-bg-danger-30
style classes from the surroundingdiv
element 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>
Save the file. 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/ActivityItem
directory and open theActivityItemContainer.tsx
file in an editor. -
Add an
import
statement for the following Preact hooks to the top of the file.import { useState, useCallback } from "preact/hooks";
-
Replace the
Props
type alias.type Props = { data?: MutableArrayDataProvider<ActivityItem["id"], ActivityItem>; selectedActivity: Item | null; onItemChanged: (item: Item) => void; };
-
Add a
DEFAULT_ACTIVITY_ITEM_STATE
variable.const DEFAULT_ACTIVITY_ITEM_STATE: Partial<Item> = {};
-
Add the following code before the
return
statement in theActivityItemContainer
function definition.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
onFirstSelectedItemChanged
attribute and replace thedata
attribute. Also delete theoj-bg-success-20
style class from thediv
element 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/ItemDetail
directory and openItemDetailContainer.tsx
in an editor. -
In the
return
statement of theItemDetailContainer
function, delete theoj-bg-neutral-30
style class from thediv
element 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-app
directory and run the virtual DOM app.npx ojet serve
-
In the virtual DOM app, click the Baseball activity.
The Activities list selection triggers the
selectedActivityChanged
event 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
selectedActivityItemChanged
event handler. The virtual DOM app renders the Item Detail 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
selectedItemChanged
event 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 7, to verify the content changes.
Description of the illustration resized_master_detail_list.png
-
Close the browser window or tab that displays your running virtual DOM app.
-
In the terminal window, press Ctrl+C, and if prompted, enter
y
to 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.zip
file, rename it asJET-Virtual-DOM-app.zip
, and extract the contents to theJET-Virtual-DOM-app
directory. -
In the terminal window, navigate to the
JET-Virtual-DOM-app
directory and restore the Oracle JET virtual DOM app.npm install
-
Wait for confirmation.
Success: Restore complete
The 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
y
to exit the Oracle JET tooling batch job.
Next Step
To proceed to the first tutorial in the next learning path in this series, click here.
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-03
February 2024
Copyright © 2022, 2024, Oracle and/or its affiliates.