I saw an interesting question in the APEX discussion forum this morning asking how a Popup LOV in an interactive grid could show only the items that were not already referenced in the grid. It’s a question I’d asked myself multiple times before, but one whose answer I hadn’t researched until today…
My solution combines a tip from my colleague Jeff Kemp’s article Interactive Grid: Custom Select List on each row with the get_ig_data
plug-in that simplifies using pending grid data in SQL or PL/SQL. Fellow Oracle employee Bud Endress had mentioned the plug-in to me multiple times and I watched the APEX Instant Tips #66: Getting Oracle APEX IG data video with Insum’s Anton Nielsen and Michelle Skamene to learn more. You can download the sample app at the end to try it out yourself.
Overview of the Data Model
The sample uses the following simple data model to create or edit orders for items from an inventory comprised of twenty-six different food items from Apple and Banana to Yuzu and Zucchini.
The simple order create and edit page lets you type in an order comment, and an interactive grid of food items and their quantities. The goal was to have the popup LOV display only the items that aren’t already mentioned in other grid rows. As shown below, if the order being created or edited already includes Banana and Apple then the LOV for another row leaves those out of the list.
Getting JSON Grid Data in a Page Item
The get_ig_data
dynamic action plugin copies data from an interactive grid and places it in a JSON format into a page item. I first downloaded the get_ig_data
plug-in from here on apex.world, and installed it into my app. Then I created a hidden page item P3_GRID_JSON_CONTENT
to contain the JSON. Finally, I added a dynamic action step using the plug-in to execute when the value of the ITEM_ID
column in the grid gets changed.
As shown in the figure below, it’s configured to only include the value of the ITEM_ID
column in the grid rows and to return the JSON into the (hidden) P3_GRID_JSON_CONTENT
page item. Notice that I ensured the Fire on Initialization switch was set to ON so that on page load the JSON would be populated into the hidden page item as well.
Including the JSON in the LOV Query
Initially I left the P3_GRID_JSON_CONTENT
page item visible by setting it to be a Display Only item type. This let me study the JSON format the plug-in creates. After selecting Banana and Apple, I saw that the JSON looked like this:
[
{"ITEM_ID":{"v":"2","d":"Banana"},"INSUM$ROW":1},
{"ITEM_ID":{"v":"1","d":"Apple"},"INSUM$ROW":2}
]
I noticed that it was an array of JSON objects, each containing an ITEM_ID
property for the column I’d configured the plug-in to include. Since the ITEM_ID
is an LOV-based column, the plug-in provides the value as another JSON object with v
and d
properties, giving me access to both the return value and the user-friendly display string. For my purposes, I only needed the return value, so I updated the ITEM_ID
column’s Popup LOV SQL Query to look like the statement below. It includes a where id not in (...)
clause to elminate the set of item ids we get from the grid JSON document. Using an appropriate json_table()
clause in the subselect, I query just the v
property of the ITEM_ID
property of each row in the JSON.
select name d, id r
from eba_demo_item
where id not in (select item_id
from json_table(:P3_GRID_JSON_CONTENT, '$[*]'
columns (
item_id number path '$.ITEM_ID.v'
)) where item_id is not null)
order by name
Sending Pending Grid Data to the Server
Notice that the LOV SQL Query above references the page item bind variable :P3_GRID_JSON_CONTENT
. That hidden page item contains pending edits that might not yet be saved in the database, so we need to ensure that this client-side information is submitted to the server when the Popup LOV performs its request to the server to retrieve its data. This is where the trick I learned from Jeff Kemp’s article came into play. I was unable to find the Page Items to Submit field in the property editor, where I knew I needed to type in P3_GRID_JSON_CONTENT
to achieve the result I wanted. His tip involved first setting the Parent Column(s) property to the primary key column name. In my case, this column is named ID
. That column won’t be changing, but providing a parent column value “unlocks” the ability to set the Page Items to Submit property. After performing those two steps, the page designed looked like the figure below.
This was all that was required to achieve the goal. Unfortunately, I later learned that the original forum question asker was using APEX version 19.1 and verified that the earliest APEX version the get_ig_data
plug-in supports is 20.1… d’oh! So while my sample didn’t provide him a ready-to-use solution for APEX 19.1, it did help me learn a few cool new tricks about APEX in the process.
Downloading the Sample
You can download the APEX 23.1 sample app from here and give it a spin for yourself. Thanks again to Jeff, Anton, and Michelle for the useful article and video.
P.S. If the grid may be long or filtered, you might consider augmenting this idea by changing the where id not in (select …)
statement to also include the list of existing ITEM_ID
values in the EBA_DEMO_ITEM_ORDER_LINES
where the ORDER_ID = :P3_ID
and then also passing the P3_ID
as one of the “Page Items to Submit”.