Changes between Initial Version and Version 1 of S3/DataTable


Ignore:
Timestamp:
04/12/13 18:58:42 (12 years ago)
Author:
Dominic König
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • S3/DataTable

    v1 v1  
     1= S3DataTable =
     2[[TOC]]
     3
     4''This page is currently being reworked...''
     5
     6== Introduction ==
     7Sahana Eden uses the !JavaScript library !DataTables http://www.datatables.net to display results returned from the database. The !DataTables library provides a lot of properties and functions that can customise the table that will be produced. Sahana Eden doesn't expose all of the functionality that is available within the !DataTables library this makes it easy to get !DataTables up and running and it also ensures a consistent look and feel. However, it is possible to customise the !DataTables through the Sahana Eden framework.
     8== The Basics ==
     9The Sahana Eden framework will produce a list of resources and put them in a !DataTable however sometimes it is necessary to build a table for a specific task or to have multiple tables on the same page. To do this is it necessary to build a controller to manage the table.
     10
     11Probably the simplest type of table will be one where all the data is sent from the server to the client and no server side pagination is required. This can be set up as follows:
     12{{{
     13#!div style="font-size: 80%"
     14Controller code snippet:
     15  {{{#!python
     16        from s3.s3utils import S3DataTable
     17        # Set up the resource
     18        resource = s3db.resource("inv_warehouse")
     19        # Find out how many records are in the resource
     20        totalrows = resource.count()
     21        list_fields = ["id",
     22                       "name",
     23                       "organisation_id",
     24                       ]
     25        # Get all the data from the resource
     26        rows = resource.select(list_fields,
     27                               orderby="organisation_id",
     28                               start=0,
     29                               limit=totalrows,
     30                               )
     31        if rows:
     32            # Format the resource data and pass them through their default represent
     33            data = resource.extract(rows,
     34                                    list_fields,
     35                                    represent=True,
     36                                    )
     37            # Get the resource fields
     38            rfields = resource.resolve_selectors(list_fields)[0]
     39            # Create the default S3DataTable
     40            dt = S3DataTable(rfields, data)
     41            # create default actions buttons for the dataTable
     42            dt.defaultActionButtons(resource)
     43            # Create the html for the dataTable
     44            warehouses = dt.html(totalrows,
     45                                 totalrows,
     46                                 "warehouse_list",
     47                                 dt_pagination="false",
     48                                 )
     49        else:
     50            warehouses = T("No warehouses exist")
     51   }}}
     52}}}
     53This code gets the rows from the resource and passes the data into the S3DataTable html() function. The extra parameter of note is the dt_pagination which when set to 'false' will turn server side pagination off. All the data will be sent to the client and !DataTables will manage the filtering and sorting itself.
     54
     55The next stage is to build a controller that can manage pagination. To do this the controller will need to additionally manage requests from !DataTables for more data.  This can be set up as follows:
     56{{{
     57#!div style="font-size: 80%"
     58Controller code snippet:
     59  {{{#!python
     60        from s3.s3utils import S3DataTable
     61        vars = request.get_vars
     62        resource = s3db.resource("inv_warehouse")
     63        # When a request is sent from DataTables it sends various information
     64        # about what data the user has requested, this includes details about
     65        # records the user wants and any sort or the filter instructions
     66
     67        # Get the start and end details from dataTables
     68        start = int(vars.iDisplayStart) if vars.iDisplayStart else 0
     69        limit = int(vars.iDisplayLength) if vars.iDisplayLength else s3mgr.ROWSPERPAGE
     70        totalrows = resource.count()
     71        list_fields = ["id",
     72                       "name",
     73                       "organisation_id",
     74                       ]
     75        # Get the filter and sort instructions from dataTables
     76        rfields = resource.resolve_selectors(list_fields)[0]
     77        (orderby, filter) = S3DataTable.getControlData(rfields, request.vars)
     78        # Now set up the resource filter and find out how many row are in the filtered resource
     79        resource.add_filter(filter)
     80        filteredrows = resource.count()
     81        # Get all the data from the resource
     82        rows = resource.select(list_fields,
     83                               orderby="organisation_id",
     84                               start=start,
     85                               limit=limit,
     86                               )
     87        if rows:
     88            data = resource.extract(rows,
     89                                    list_fields,
     90                                    represent=True,
     91                                    )
     92            dt = S3DataTable(rfields, data)
     93            dt.defaultActionButtons(resource)
     94            if request.extension == "html":
     95                # Get the html for the initial call to the dataTable
     96                warehouses = dt.html(totalrows,
     97                                     filteredrows,
     98                                     "warehouse_list",
     99                                     )
     100            else:
     101                # Get any subsequent request for data which will be sent back as json
     102                warehouse = dt.json(totalrows,
     103                                    filteredrows,
     104                                    "warehouse_list",
     105                                    int(vars.sEcho),
     106                                    )
     107                return warehouse
     108        else:
     109            warehouses = T("No warehouses exist")
     110   }}}
     111}}}
     112Now the controller needs to manage the two standard request extensions for dataTables: html which is used for the initial table; and aaData which is used for subsequent calls. When the data is prepared for the dataTable it needs to know the total rows in the table and the number of rows that are available after filtering, the filter information is returned from dataTables and the static helper method S3DataTable.getControlData will return the filter and sort information which the user has set up. The json method requires an extra parameter the sEcho which it passes to the server itself. This value just needs to be returned back to the client. '''Note''' that the html call now no longer requires the dt_pagination parameter.
     113
     114== Configuring the table ==
     115=== Adding action buttons ===
     116The default buttons can be expanded upon by creating a list of buttons to be added to the table. Each button is defined by a dictionary which describes the button. The dictionary can consist of the following items:
     117||= Item Name =||= Description =||
     118|| label || The name that will appear on the button ||
     119|| _class || The class used to display the button, typically use "action-btn" for text and "action-icon" for icons ||
     120|| url || The url which will be used when the button is pressed. Use "[id]" for substituting the id of the record ||
     121|| icon || Optionsal, the icon to be used in place of text ||
     122{{{
     123#!div style="font-size: 80%"
     124Controller code snippet:
     125  {{{#!python
     126        from s3.s3utils import S3DataTable
     127        vars = request.get_vars
     128        resource = s3db.resource("inv_warehouse")
     129        start = int(vars.iDisplayStart) if vars.iDisplayStart else 0
     130        limit = int(vars.iDisplayLength) if vars.iDisplayLength else s3mgr.ROWSPERPAGE
     131        totalrows = resource.count()
     132        list_fields = ["id",
     133                       "name",
     134                       "organisation_id",
     135                       ]
     136        rfields = resource.resolve_selectors(list_fields)[0]
     137        (orderby, filter) = S3DataTable.getControlData(rfields, request.vars)
     138        resource.add_filter(filter)
     139        filteredrows = resource.count()
     140        rows = resource.select(list_fields,
     141                               orderby="organisation_id",
     142                               start=start,
     143                               limit=limit,
     144                               )
     145        if rows:
     146            data = resource.extract(rows,
     147                                    list_fields,
     148                                    represent=True,
     149                                    )
     150            dt = S3DataTable(rfields, data)
     151            dt.defaultActionButtons(resource)
     152            if request.extension == "html":
     153                custom_actions = [dict(label=str(T("Stock")),
     154                                  _class="action-btn",
     155                                  url=URL(c="inv", f="warehouse",
     156                                          args=["[id]", "inv_item"]
     157                                          )
     158                                  ),
     159                                 ]
     160                dt.defaultActionButtons(resource, custom_actions)
     161                warehouses = dt.html(totalrows,
     162                                     filteredrows,
     163                                     "warehouse_list",
     164                                     )
     165            else:
     166                warehouse = dt.json(totalrows,
     167                                    filteredrows,
     168                                    "warehouse_list",
     169                                    int(request.vars.sEcho),
     170                                    )
     171                return warehouse
     172        else:
     173            warehouses = T("No warehouses exist")
     174   }}}
     175}}}
     176
     177----
     178- [wiki:S3 S3 API Guide]
     179- DeveloperGuidelines