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/views
directory and open thedashboard.html
file in an editor. -
Find the
div
element whereid="container"
, and then delete it and theoj-module
custom 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
div
element whereid="activityItemsContainer"
, add anh3
heading 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
h3
element you created, add anoj-list-view
custom HTML element to display the Activity Items detail list and atemplate
element with aslot
attribute 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
template
element with aslot
attribute as a placeholder instantiates the contents of the Activity Items detail list at runtime. -
Within the
template
element you created, add threediv
elements 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.image
and$current.data.name
code binds the data, and an HTMLtemplate
element exposes an image and activity item name for the Activity Items detail list. The$current
prefix represents the current child object that the data provider for the Oracle JET List View component passes into the template. -
Save the
dashboard.html
file 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/viewModels
directory and open thedashboard.ts
file in an editor. -
At the top of the
dashboard.ts
file, after the type declaration ofActivity
, declare the followingItem
type.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_view
up 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-element
import statements. -
Add an import statement for the
ojavatar
module to the import list. Theojavatar
module 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.activityDataProvider
definition, within theconstructor()
function, add definitions foractivitiesArray
anditemsArray
. Then declarethis.itemsDataProvider
as 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
large
andmoduleConfig
, and add type annotations foritemsArray
anditemsDataProvider
.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
itemsArray
type 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_Application
directory and run the app.npx ojet serve
In the Dashboard tab, the web browser displays the databound detail list with the Activity Items header.
Description of the illustration formatted_master_detail_list.png
-
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.html
file, within thediv
element whereid="itemDetailsContainer"
, find the Item Details heading. Underneath the heading, add a horizontal rule followed by anoj-avatar
custom 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
itemData
observable populates the Oracle JET Avatar component by using a data provider instance that you create in the app viewModel. TheitemData().image
function is the Knockout observable notation for reading the current value of a data item. The data item is identified by theimage
property of the Activity Items child object. -
In
dashboard.html
, below the closing tag of theoj-avatar
element you created, delete theoj-label for="basicSelect"
custom HTML element and theoj-select-single
element. -
Below the closing tag of the
oj-avatar
element you created, add fourdiv
elements withoj-bind-text
custom 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
itemData
observables 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
, andid
properties of the Activity Items child object. -
Below the
div
elements you created, delete theoj-chart id="barChart"
custom HTML element. -
After the closing
</div>
tag of thediv id="itemId"
element, add a newdiv
element and anoj-chart
custom 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
pieSeriesValue
observable populates the Oracle JET Pie Chart component by using a data array that you create in the app viewModel. -
Save the
dashboard.html
file.Your file should look similar to final-detail-list-dashboard-html.txt.
-
Navigate to the
JET_Web_Application/src/css
directory and open theapp.css
file 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.ts
file, delete the code block that begins withthis.val
and 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
itemData
andpieSeriesValue
type annotations to theDashboardViewModel
class.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.itemsDataProvider
statement, set theitemData
observable 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
itemData
observable declaration, set thethis.pieSeriesValue
observable.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.
Description of the illustration formatted_master_detail_items_list.png
-
Close the browser window or tab that displays your running web 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 next tutorial in this learning path, 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.
Create the detail view in an Oracle JET web app
F11921-06
February 2024
Copyright © 2022, 2024, Oracle and/or its affiliates.