Changes between Version 25 and Version 26 of DeveloperGuidelines/DataTables


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

--

Legend:

Unmodified
Added
Removed
Modified
  • DeveloperGuidelines/DataTables

    v25 v26  
    11[[TOC]]
    22= !DataTables =
    3 '''This page is being reworked...'''
    4 == Introduction ==
    5 Sahana 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.
    6 == The Basics ==
    7 The 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.
    83
    9 Probably 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:
    10 {{{
    11 #!div style="font-size: 80%"
    12 Controller code snippet:
    13   {{{#!python
    14         from s3.s3utils import S3DataTable
    15         # Set up the resource
    16         resource = s3db.resource("inv_warehouse")
    17         # Find out how many records are in the resource
    18         totalrows = resource.count()
    19         list_fields = ["id",
    20                        "name",
    21                        "organisation_id",
    22                        ]
    23         # Get all the data from the resource
    24         rows = resource.select(list_fields,
    25                                orderby="organisation_id",
    26                                start=0,
    27                                limit=totalrows,
    28                                )
    29         if rows:
    30             # Format the resource data and pass them through their default represent
    31             data = resource.extract(rows,
    32                                     list_fields,
    33                                     represent=True,
    34                                     )
    35             # Get the resource fields
    36             rfields = resource.resolve_selectors(list_fields)[0]
    37             # Create the default S3DataTable
    38             dt = S3DataTable(rfields, data)
    39             # create default actions buttons for the dataTable
    40             dt.defaultActionButtons(resource)
    41             # Create the html for the dataTable
    42             warehouses = dt.html(totalrows,
    43                                  totalrows,
    44                                  "warehouse_list",
    45                                  dt_pagination="false",
    46                                  )
    47         else:
    48             warehouses = T("No warehouses exist")
    49    }}}
    50 }}}
    51 This 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.
    52 
    53 The 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:
    54 {{{
    55 #!div style="font-size: 80%"
    56 Controller code snippet:
    57   {{{#!python
    58         from s3.s3utils import S3DataTable
    59         vars = request.get_vars
    60         resource = s3db.resource("inv_warehouse")
    61         # When a request is sent from DataTables it sends various information
    62         # about what data the user has requested, this includes details about
    63         # records the user wants and any sort or the filter instructions
    64 
    65         # Get the start and end details from dataTables
    66         start = int(vars.iDisplayStart) if vars.iDisplayStart else 0
    67         limit = int(vars.iDisplayLength) if vars.iDisplayLength else s3mgr.ROWSPERPAGE
    68         totalrows = resource.count()
    69         list_fields = ["id",
    70                        "name",
    71                        "organisation_id",
    72                        ]
    73         # Get the filter and sort instructions from dataTables
    74         rfields = resource.resolve_selectors(list_fields)[0]
    75         (orderby, filter) = S3DataTable.getControlData(rfields, request.vars)
    76         # Now set up the resource filter and find out how many row are in the filtered resource
    77         resource.add_filter(filter)
    78         filteredrows = resource.count()
    79         # Get all the data from the resource
    80         rows = resource.select(list_fields,
    81                                orderby="organisation_id",
    82                                start=start,
    83                                limit=limit,
    84                                )
    85         if rows:
    86             data = resource.extract(rows,
    87                                     list_fields,
    88                                     represent=True,
    89                                     )
    90             dt = S3DataTable(rfields, data)
    91             dt.defaultActionButtons(resource)
    92             if request.extension == "html":
    93                 # Get the html for the initial call to the dataTable
    94                 warehouses = dt.html(totalrows,
    95                                      filteredrows,
    96                                      "warehouse_list",
    97                                      )
    98             else:
    99                 # Get any subsequent request for data which will be sent back as json
    100                 warehouse = dt.json(totalrows,
    101                                     filteredrows,
    102                                     "warehouse_list",
    103                                     int(vars.sEcho),
    104                                     )
    105                 return warehouse
    106         else:
    107             warehouses = T("No warehouses exist")
    108    }}}
    109 }}}
    110 Now 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.
    111 
    112 == Configuring the table ==
    113 === Adding action buttons ===
    114 The 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:
    115 ||= Item Name =||= Description =||
    116 || label || The name that will appear on the button ||
    117 || _class || The class used to display the button, typically use "action-btn" for text and "action-icon" for icons ||
    118 || url || The url which will be used when the button is pressed. Use "[id]" for substituting the id of the record ||
    119 || icon || Optionsal, the icon to be used in place of text ||
    120 {{{
    121 #!div style="font-size: 80%"
    122 Controller code snippet:
    123   {{{#!python
    124         from s3.s3utils import S3DataTable
    125         vars = request.get_vars
    126         resource = s3db.resource("inv_warehouse")
    127         start = int(vars.iDisplayStart) if vars.iDisplayStart else 0
    128         limit = int(vars.iDisplayLength) if vars.iDisplayLength else s3mgr.ROWSPERPAGE
    129         totalrows = resource.count()
    130         list_fields = ["id",
    131                        "name",
    132                        "organisation_id",
    133                        ]
    134         rfields = resource.resolve_selectors(list_fields)[0]
    135         (orderby, filter) = S3DataTable.getControlData(rfields, request.vars)
    136         resource.add_filter(filter)
    137         filteredrows = resource.count()
    138         rows = resource.select(list_fields,
    139                                orderby="organisation_id",
    140                                start=start,
    141                                limit=limit,
    142                                )
    143         if rows:
    144             data = resource.extract(rows,
    145                                     list_fields,
    146                                     represent=True,
    147                                     )
    148             dt = S3DataTable(rfields, data)
    149             dt.defaultActionButtons(resource)
    150             if request.extension == "html":
    151                 custom_actions = [dict(label=str(T("Stock")),
    152                                   _class="action-btn",
    153                                   url=URL(c="inv", f="warehouse",
    154                                           args=["[id]", "inv_item"]
    155                                           )
    156                                   ),
    157                                  ]
    158                 dt.defaultActionButtons(resource, custom_actions)
    159                 warehouses = dt.html(totalrows,
    160                                      filteredrows,
    161                                      "warehouse_list",
    162                                      )
    163             else:
    164                 warehouse = dt.json(totalrows,
    165                                     filteredrows,
    166                                     "warehouse_list",
    167                                     int(request.vars.sEcho),
    168                                     )
    169                 return warehouse
    170         else:
    171             warehouses = T("No warehouses exist")
    172    }}}
    173 }}}
     4  * see [wiki:S3/DataTable S3DataTable]