Create the detail view in an Oracle JET web app
Introduction
Oracle JavaScript Extension Toolkit (Oracle JET) components preserve the hierarchical relationship of master and detail data objects, as defined by the data source. In the viewModel for the Oracle JET web app, you can use the Oracle JET API to create a data provider object. The object represents a data array that you populate from the child data objects of a JavaScript Object Notation (JSON) document data store. The Oracle JET data provider fetches the child data objects based on the id key attribute of the current parent data object. In the view for the Oracle JET web app, the data attribute of the Oracle JET List View component binds to the data provider through a Knockout observable. The Knockout observable is also declared in the app’s viewModel source code. This code populates the observable as an instance of the detail list data provider.
Objectives
In this tutorial, you will read master-detail hierarchical data from a local JSON document and display the detail view in an Oracle JET web app. You learn how to data bind items of the child data objects to populate an Oracle JET List View component, multiple Oracle JET Input Text components, and an Oracle JET Chart component.
Prerequisites
- A development environment set up to create Oracle JET web apps that includes an installation of Node.js
- Completion of the previous tutorial in this learning path, Create the Master View in an Oracle JET Web Application
Task 1: Data Bind the Activity Items Detail List in the View
Replace the Activity Items list bound to static data with an Oracle JET List View component bound to multiple data items of Activity Items child objects.
-
Navigate to the
JET_Web_Application/src/ts/viewsdirectory and open thedashboard.htmlfile in an editor. -
Find the
divelement whereid="container", and then delete it and theoj-modulecustom element that it contains.<div id="activityItemsContainer" class="oj-flex-item oj-md-6 oj-sm-12"> <div id="container"> <oj-module config="[[moduleConfig]]"></oj-module> </div> </div> <!-- Delete the div element with id="container" so that your code is similar to the following: --> <div id="activityItemsContainer" class="oj-flex-item oj-md-6 oj-sm-12"></div> . . . -
Within the
divelement whereid="activityItemsContainer", add anh3heading element for the Activity Items detail list.<div id="activityItemsContainer" class="oj-flex-item oj-md-6 oj-sm-12"> <h3 id="itemsListHeader">Activity Items</h3> </div> -
After the closing tag of the
h3element you created, add anoj-list-viewcustom HTML element to display the Activity Items detail list and atemplateelement with aslotattribute to apply to the contents of the detail list.<h3 id="itemsListHeader">Activity Items</h3> <oj-list-view id="itemsList" class="item-display" data="[[itemsDataProvider]]" aria-labelledby="itemsListHeader" gridlines.item="visible" > <template slot="itemTemplate"> </template> </oj-list-view>The Oracle JET List View component used in an inline HTML
templateelement with aslotattribute as a placeholder instantiates the contents of the Activity Items detail list at runtime. -
Within the
templateelement you created, add threedivelements with code to bind the image and name data items for each Activity Items child object.<template slot="itemTemplate"> <div class="oj-flex no-wrap"> <span class="demo-thumbnail oj-flex-item" :style.background-image="[[' url('+$current.data.image+')']]" ></span> <div class="demo-content oj-flex-item"> <div> <strong> <oj-bind-text value="[[$current.data.name]]"></oj-bind-text> </strong> </div> </div> </div> </template>The
$current.data.imageand$current.data.namecode binds the data, and an HTMLtemplateelement exposes an image and activity item name for the Activity Items detail list. The$currentprefix represents the current child object that the data provider for the Oracle JET List View component passes into the template. -
Save the
dashboard.htmlfile and leave it open in your editor.Your file should look similar to detail-list-task1-dashboard-html.txt.
Task 2: Create the Activity Items Child Objects in the ViewModel
Replace the oj-module inline template that you created in the previous learning path to display the Activity Items list with a JSON document call to read the Activity Items child objects from a local JSON document. In itemsDataProvider, create an instance of an Oracle JET MutableArrayDataProvider class that represents an array of child objects defined by the JSON document. Then bind the itemsArray instance to an itemsDataProvider observable. The Oracle JET List View component in the view references this observable on its data attribute to display the Activity Items detail list.
-
Navigate to the
JET_Web_Application/src/ts/viewModelsdirectory and open thedashboard.tsfile in an editor. -
At the top of the
dashboard.tsfile, after the type declaration ofActivity, declare the followingItemtype.type Activity = { id: number; }; type Item = { id: number; name: string; short_desc: string; price: number; quantity: number; quantity_shipped: number; quantity_instock: number; activity_id: number; image: string; value?: string; }; . . . -
Delete the code from the declaration of
const lg_xl_viewup to but not including the declaration ofthis.chartTypes. The code block ends with a comment line that readsEnd of oj-module code. A JSON document call will replace the static data and inline template code.Your file should look similar to detail-list-task2a-dashboard-ts.txt.
-
From the module imports at the top of
dashboard.ts, delete the unusedHtmlUtils,ResponsiveUtils,ResponsiveKnockoutUtils, andojmodule-elementimport statements. -
Add an import statement for the
ojavatarmodule to the import list. Theojavatarmodule supports the view in the next section of this tutorial.import * as AccUtils from "../accUtils"; import * as ko from "knockout"; import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider"); import "ojs/ojselectsingle"; import "ojs/ojlabel"; import "ojs/ojchart"; import * as storeData from "text!../store_data.json"; import "ojs/ojlistview"; import "ojs/ojavatar"; -
After the
this.activityDataProviderdefinition, within theconstructor()function, add definitions foractivitiesArrayanditemsArray. Then declarethis.itemsDataProvideras an instance ofMutableArrayDataProvider. This parses the store data and makes the child objects of the first Activity parent object available in the Oracle JET List View component. In the next tutorial, you set the Activity object dynamically by using event handlers.. . . let activitiesArray = JSON.parse(storeData); let itemsArray = activitiesArray[0].items; this.itemsDataProvider = new MutableArrayDataProvider<Item["id"], Item>( itemsArray, { keyAttributes: "id" } ); } // closing bracket of constructor function . . .Then remove the unused type annotations for
largeandmoduleConfig, and add type annotations foritemsArrayanditemsDataProvider.class DashboardViewModel { chartTypes: Array<Object>; chartTypesDP: MutableArrayDataProvider<ChartType["value"], ChartType>; chartData: Array<Object>; chartDataProvider: MutableArrayDataProvider<string, {}>; activityDataProvider: MutableArrayDataProvider<Activity["id"], Activity>; val: ko.Observable<string>; itemsArray!: Array<Object>; itemsDataProvider: MutableArrayDataProvider<Item["id"], Item>;We use the definite assignment assertion (!) for the
itemsArraytype annotation to communicate to TypeScript that we initialised this property in the previous step.Your file should look similar to detail-list-task2b-dashboard-ts.txt.
Task 3: Run the Web App
-
In the terminal window, change to the
JET_Web_Applicationdirectory and run the app.npx ojet serveIn the Dashboard tab, the web browser displays the databound detail list with the Activity Items header.

-
Leave the terminal window and the browser that displays your web app open.
Task 4: Data Bind Item Details and Pie Chart in the View
Replace the Item Details pie and bar charts with the following elements:
- An Oracle JET Avatar component bound to the item image of an Activity Items child object
- Multiple Oracle JET Text Field components bound to the data items of that Activity Items child object
- A Pie Chart component bound to chart data items of the same Activity Items child object
-
In the
dashboard.htmlfile, within thedivelement whereid="itemDetailsContainer", find the Item Details heading. Underneath the heading, add a horizontal rule followed by anoj-avatarcustom HTML element bound to the image data item for an Activity Items child object.<div id="itemDetailsContainer" class="oj-flex-item oj-panel oj-bg-neutral-30 oj-md-6 oj-sm-12"> <h3>Item Details</h3> <hr class="hr-margin" /> <oj-avatar role="img" size="lg" :aria-label="[['product image for '+ itemData().name]]" :src="[[itemData().image]]" class="float-right"> </oj-avatar> </div>The
itemDataobservable populates the Oracle JET Avatar component by using a data provider instance that you create in the app viewModel. TheitemData().imagefunction is the Knockout observable notation for reading the current value of a data item. The data item is identified by theimageproperty of the Activity Items child object. -
In
dashboard.html, below the closing tag of theoj-avatarelement you created, delete theoj-label for="basicSelect"custom HTML element and theoj-select-singleelement. -
Below the closing tag of the
oj-avatarelement you created, add fourdivelements withoj-bind-textcustom HTML elements bound to the name, short description, price, and ID data items of an Activity Items child object.. . . </oj-avatar> <div id="itemName" class="data-name"> <oj-bind-text value="[[itemData().name]]"></oj-bind-text> </div> <div id="itemDesc" class="data-desc"> <oj-bind-text value="[[itemData().short_desc]]"></oj-bind-text> </div> <div id="itemPrice"> <oj-bind-text value="[['Price: ' + itemData().price + ' each']]"></oj-bind-text> </div> <div id="itemId"> <oj-bind-text value="[['Item Id: ' + itemData().id]]"></oj-bind-text> </div> . . .The
itemDataobservables populate the Oracle JET Text Binding component by using a data provider that you create in the app viewModel. TheitemData().<prop_name>function reads the current value of the named data item. The data items are identified by thename,short_desc,price, andidproperties of the Activity Items child object. -
Below the
divelements you created, delete theoj-chart id="barChart"custom HTML element. -
After the closing
</div>tag of thediv id="itemId"element, add a newdivelement and anoj-chartcustom HTML element bound to a pie chart series for an Activity Items child object.. . . <div id="itemId"> <oj-bind-text value="[['Item Id: ' + itemData().id]]"></oj-bind-text> </div> <div> <oj-chart type="pie" series="[[pieSeriesValue]]" animation-on-display="auto" animation-on-data-change="auto" hover-behavior="dim" legend.position="bottom" class="chartStyle" > </oj-chart> </div> . . .The
pieSeriesValueobservable populates the Oracle JET Pie Chart component by using a data array that you create in the app viewModel. -
Save the
dashboard.htmlfile.Your file should look similar to final-detail-list-dashboard-html.txt.
-
Navigate to the
JET_Web_Application/src/cssdirectory and open theapp.cssfile to add the following style definitions..hr-margin { margin-top: 12px; } .data-name { font-size: 20px; font-weight: bolder; } .data-desc { font-size: 14px; font-weight: 400; font-style: italic; margin-bottom: 10px; } .float-right { float: right; }Your file should look similar to app-css-final.txt.
Task 5: Set Observables for Item Details and Pie Chart Components in the ViewModel
Get a data item from the Activity Items child object, and populate observables to data bind view components. In the view, the value attribute of the various Item Details components references the itemData observable. And the series attribute of the Pie Chart component references the pieSeriesValue observable bound to chart data from the same data item.
-
In the
dashboard.tsfile, delete the code block that begins withthis.valand ends withthis.chartTypesDP. Also delete the unused type annotations for the removed variables. Your type annotations list and the beginning of yourconstructor()function should look similar to the following example.class DashboardViewModel { activityDataProvider: MutableArrayDataProvider<Activity["id"], Activity>; itemsArray!: Array<Object>; itemsDataProvider: MutableArrayDataProvider<Item["id"], Item>; constructor() { this.activityDataProvider = new MutableArrayDataProvider< Activity["id"], Activity >(JSON.parse(storeData), { keyAttributes: "id", }); . . . -
Add the
itemDataandpieSeriesValuetype annotations to theDashboardViewModelclass.class DashboardViewModel { activityDataProvider: MutableArrayDataProvider<Activity["id"], Activity>; itemsArray!: Array<Object>; itemsDataProvider: MutableArrayDataProvider<Item["id"], Item>; itemData: ko.Observable<any>; pieSeriesValue: ko.ObservableArray; constructor() { . . . -
After the
this.itemsDataProviderstatement, set theitemDataobservable with a reference to the first Activity parent object and the first Activity Item child object associated with that activity in the JSON document.this.itemsDataProvider = new MutableArrayDataProvider<Item["id"], Item>( itemsArray, { keyAttributes: "id" } ); this.itemData = ko.observable(''); this.itemData(activitiesArray[0].items[0]); } // End of constructor function -
Finally, underneath the
itemDataobservable declaration, set thethis.pieSeriesValueobservable.this.itemData = ko.observable(""); this.itemData(activitiesArray[0].items[0]); this.pieSeriesValue = ko.observableArray([{}]); let pieSeries = [ { name: "Quantity in Stock", items: [this.itemData().quantity_instock] }, { name: "Quantity Shipped", items: [this.itemData().quantity_shipped] }, ]; this.pieSeriesValue(pieSeries);Your file should look similar to observables-task5-dashboard-ts.txt.
Task 6: View the Master and Detail Lists
-
Return to the browser to view the changes in your web app.
In the Dashboard tab of your web app, the databound Oracle JET text fields, avatar, and pie chart are displayed in the Items Details container, but the lists do not respond to selections. In the next tutorial, event handlers you create will add selection functionality.

-
Close the browser window or tab that displays your running web app.
-
In the terminal window, press Ctrl+C, and if prompted, enter
yto exit the Oracle JET tooling batch job.
Next Step
Proceed to the next tutorial in this module.
This tutorial is part of the module Master Detail Views in Oracle JET.
- Create the Master View in an Oracle JET Web App
- Create the Detail View in an Oracle JET Web App
- Handle Selection Events in an Oracle JET Web App
You can return to the learning path’s main page to access all the modules on building web 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.
Create the detail view in an Oracle JET web app
F11921-07