B4J Tutorial [BANano] Creating Master Details Grid with UOEGridTable

Ola

This tutorial is based on this BANano based lib, https://www.b4x.com/android/forum/t...-interesting-grid-that-you-might-like.105225/

The purpose here is when one needs to show Master Detail relationship between two or more related data sets.

NestedGrid.gif


Above we have grids inside grids that show players for each country.

1. We create the countries grid with a detailTemplate that will host the child grid for each record.

B4X:
Sub Initialize
    BANano.GetElement("#body").empty
    BANano.LoadLayout("#body","vCountries")
    BANano.GetElement("#body").SetStyle($"{"padding": "8px"}"$)
  
    'define the master details
    gridcountries.PrimaryKey = "id"
    gridcountries.AddColumn("id","#",gridcountries.COLUMN_TEXT, 56, False, gridcountries.ALIGN_CENTER)
    gridcountries.AddColumn("text","Name",gridcountries.COLUMN_TEXT, 0, True, gridcountries.ALIGN_LEFT)
    gridcountries.AddColumn("population","Population",gridcountries.COLUMN_TEXT,0,True,gridcountries.ALIGN_RIGHT)
    Dim countries As List
    countries.Initialize
    'countries.Add(CreateMap("id":"1","text":"Asia","population":Null,"flagUrl":Null,"checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"12","text":"Brazil","population":207350000,"flagUrl":"https://code.gijgo.com/flags/24/brazil.png","checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"14","text":"Colombia","population":49819638,"flagUrl":"https://code.gijgo.com/flags/24/colombia.png","checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"15","text":"South Africa","population":Null,"flagUrl":Null,"checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"16","text":"England","population":54786300,"flagUrl":"https://code.gijgo.com/flags/24/england.png","checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"17","text":"Germany","population":82175700,"flagUrl":"https://code.gijgo.com/flags/24/germany.png","checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"18","text":"Bulgaria","population":7101859,"flagUrl":"https://code.gijgo.com/flags/24/bulgaria.png","checked":False,"hasChildren":False))
    countries.Add(CreateMap("id":"19","text":"Poland","population":38454576,"flagUrl":"https://code.gijgo.com/flags/24/poland.png","checked":False,"hasChildren":False))
    gridcountries.SetDataSource(countries)
    'define the details grid to be nested
    gridcountries.DetailTemplate = "<div><table/></div>"
    gridcountries.refresh
End Sub

For the country data we are only showing the country name and population.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
2. Create the Players records

We create a list of records that will hold the players information. When showing the detail grid we will filter this by the country to show the child nodes.

B4X:
Sub RefreshPlayers
    'lets create the players records
    players.Initialize
    players.Add(CreateMap("id": "1", "Name": "Hristo Stoichkov", "PlaceOfBirth": "Plovdiv, Bulgaria","CountryID":"18","CountryName": "Bulgaria"))
    players.Add(CreateMap("id": "2", "Name": "Ronaldo Luis Nazario de Lima", "PlaceOfBirth": "Rio de Janeiro, Brazil", "CountryID":"12","CountryName": "Brazil"))
    players.Add(CreateMap("id": "3", "Name": "David Platt", "PlaceOfBirth": "Chadderton, Lancashire, England","CountryID":"16","CountryName": "England"))
    players.Add(CreateMap("id": "4", "Name": "Manuel Neuer", "PlaceOfBirth": "Gelsenkirchen, West Germany", "CountryID":"17", "CountryName": "Germany"))
    players.Add(CreateMap("id": "5", "Name": "James Rodríguez", "PlaceOfBirth": "Cúcuta, Colombia", "CountryID":"14", "CountryName": "Colombia"))
    players.Add(CreateMap("id": "6", "Name": "Dimitar Berbatov", "PlaceOfBirth": "Blagoevgrad, Bulgaria", "CountryID":"18", "CountryName": "Bulgaria"))
    players.Add(CreateMap("id": "7", "Name": "Robert Lewandowski", "PlaceOfBirth": "Warsaw, Poland", "CountryID":"19", "CountryName": "Poland"))
    players.Add(CreateMap("id": "8", "Name": "Mashy", "PlaceOfBirth": "East London, Eastern Cape", "CountryID":"15", "CountryName": "South Africa"))
End Sub

There are two important events to trap the details child records, DetailExpand which happens when the details button is expanded and the DetailCollapse event which happens when the details are collapsed. We will feed the details record when these events are being fired.
 

Mashiane

Expert
Licensed User
Longtime User
3. When the detail for each record is expanded, if there is existing records/table, destroy it, filter the players by country and only load the players for that country. We have set autoColumn to true so that the columns for the details grid are automatically generated.

B4X:
Sub gridcountries_DetailExpand (e As BANanoEvent, detailWrapper As BANanoObject, id As String)
    'get record
    Dim record As Map = gridcountries.GetById(id)
    Log(record)
    RefreshPlayers
    'find the table in the detailedWrapper
    Dim dw As BANanoObject = detailWrapper.RunMethod("find",Array("table"))
    'destroy the grid, clear data and remove events
    dw.RunMethod("grid", Array("destroy",True,True))
    'define the filter
    Dim params As Map = CreateMap("CountryID":id)
    'define the pager
    Dim pager As Map = CreateMap("limit":5)
    'define the options
    Dim opt As Map
    opt.Initialize
    opt.Put("title", "Players")
    opt.Put("primaryKey", "id")
    opt.Put("autoLoad", True)
    opt.Put("uiLibrary", gridcountries.UILibrary)
    opt.Put("iconsLibrary", gridcountries.IconsLibrary)
    opt.Put("params", params)
    opt.Put("dataSource", players)
    opt.Put("autoGenerateColumns", True)
    opt.Put("pager", pager)
    'create the grid
    dw.RunMethod("grid", Array(opt))
    'Dim childGrid As BANanoObject = dw.RunMethod("grid", Array(opt))
    'childGrid.RunMethod("reload", Array(CreateMap("CountryID":id)))
End Sub

Each country in the countries records has an ID, we use this id to filter the records to be displayed for the players. To create the grid we run the dw.RunMethod("grid"...) command passing it options for the grid. Simple as ABC.
 

Mashiane

Expert
Licensed User
Longtime User
4. To conserve memory, when the detail grid is closed, we destroy the child grid and linked events.

B4X:
Sub gridcountries_DetailCollapse (e As BANanoEvent, detailWrapper As BANanoObject, id As String)
    'find the table in the detailedWrapper
    Dim dw As BANanoObject = detailWrapper.RunMethod("find",Array("table"))
    'destry the grid, clear data and remove events
    dw.RunMethod("grid", Array("destroy",True,True))
End Sub
 
Top