Hello there follow web2py users, First of all, Massimo, thanks for the great work you have done to get web2py to this high level of functionality.
I recently started using it for a project and was faced with a challenge: in SQLFORM.grid, when a table has many fields, the users have to scroll to the far right to get to the action buttons, and this has proved cumbersome to them. The same goes for the links that we are allowed to add to the grid. I chose to resolve this issue by adding two extra optional arguments to SQLFORM.grid, namely buttons_placement and links_placement The two are expected to have a value among 'left', 'right', 'both' Both default to 'right' to maintain backward compatibility. If you set them to 'left' the corresponding column(s) will appear at the beginning of the grid (1st column). If you set them to 'right, they will appear at the end (as it was already working) If you set them to 'both', the columns will appear twice, at the beginning and at the end (usefull for large tables where the user can locate the column he wants to decide upon and find a button closeby, either at the beginning or the end) I am attaching a patch against the stock 1.99.7 that I used to begin with. It would be great if some form of this patch would be included in future releases. Again, thanks for all the hard work you all have put into this. Nikos
diff --git a/web2py/gluon/sqlhtml.py b/web2py/gluon/sqlhtml.py index 2e70368..a121222 100644 --- a/web2py/gluon/sqlhtml.py +++ b/web2py/gluon/sqlhtml.py @@ -1421,6 +1421,8 @@ class SQLFORM(FORM): search_widget='default', ignore_rw = False, formstyle = 'table3cols', + buttons_placement = 'right', + links_placement = 'right', ): # jQuery UI ThemeRoller classes (empty if ui is disabled) @@ -1722,16 +1724,26 @@ class SQLFORM(FORM): head.append(TH(header, _class=ui.get('default',''))) if links and links_in_grid: + toadd = [] for link in links: if isinstance(link,dict): - head.append(TH(link['header'], _class=ui.get('default',''))) + toadd.append(TH(link['header'], _class=ui.get('default',''))) + + if links_placement in ['right', 'both']: + head.append(toadd) + if links_placement in ['left', 'both']: + head.insert(0, toadd) # Include extra column for buttons if needed. include_buttons_column = (details or editable or deletable or (links and links_in_grid and not all([isinstance(link, dict) for link in links]))) if include_buttons_column: - head.append(TH(_class=ui.get('default',''))) + if buttons_placement in ['right', 'both']: + head.append(TH(_class=ui.get('default',''))) + if buttons_placement in ['left', 'both']: + head.insert(0, TH(_class=ui.get('default',''))) + paginator = UL() if paginate and paginate<nrows: @@ -1827,12 +1839,17 @@ class SQLFORM(FORM): tr.append(TD(value)) row_buttons = TD(_class='row_buttons') if links and links_in_grid: + toadd = [] for link in links: if isinstance(link, dict): - tr.append(TD(link['body'](row))) + toadd.append(TD(link['body'](row))) else: if link(row): row_buttons.append(link(row)) + if links_placement in ['right', 'both']: + tr.append(toadd) + if links_placement in ['left', 'both']: + tr.insert(0,toadd) if include_buttons_column: if details and (not callable(details) or details(row)): row_buttons.append(gridbutton( @@ -1847,7 +1864,10 @@ class SQLFORM(FORM): 'buttondelete', 'Delete', callback=url(args=['delete',tablename,id]), delete='tr')) - tr.append(row_buttons) + if buttons_placement in ['right', 'both']: + tr.append(row_buttons) + if buttons_placement in ['left', 'both']: + tr.insert(0, row_buttons) tbody.append(tr) htmltable.append(tbody) htmltable = DIV(htmltable,_style='width:100%;overflow-x:auto')