B4J Tutorial [BANano] Creating Master Details Grid with UOEGridTable

Discussion in 'B4J Tutorials' started by Mashiane, Apr 29, 2019.

  1. Mashiane

    Mashiane Expert Licensed User

    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.

    Code:
    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, 56False, gridcountries.ALIGN_CENTER)
        gridcountries.AddColumn(
    "text","Name",gridcountries.COLUMN_TEXT, 0True, 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: Apr 29, 2019
    joulongleu likes this.
  2. Mashiane

    Mashiane Expert Licensed 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.

    Code:
    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.
     
    joulongleu likes this.
  3. Mashiane

    Mashiane Expert Licensed 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.

    Code:
    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.
     
    joulongleu likes this.
  4. Mashiane

    Mashiane Expert Licensed User

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

    Code:
    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
     
    joulongleu likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice