Jump to content

Preview/Discussion: RockDataTables

Recommended Posts

8 hours ago, bernhard said:

I think it is superior to (and in most cases also easier than) datatables, that's why I'm switching.

Yeah, at firts sight ag-grid looks great but have you seen http://tabulator.info/ lately? Namely the new release: http://tabulator.info/news

I have also checked out a lot of these JS table libraries and Tabulator seems to be the only one which is completely open source (MIT)  and is being actively developed. I have not used it just yet but I am planning a test drive in the near future.

Edited by szabesz
  • Like 4
Link to post
Share on other sites

thx @szabesz, haven't seen anything about tabulator so far. It looks quite similar to jquery datatables though and I have not seen anything that would not be possible using aggrid on the first sight. Or did I miss anything?

I'm quite far with my implementation of agGrid, so I'm quite sure I will not change the grid library (again) very soon ;) 

  • Like 1
Link to post
Share on other sites
4 minutes ago, bernhard said:

Or did I miss anything?

Well, I am not suggesting you should switch to it, the only thing which is clearly better to have is its MIT license. I just thought you might want to reconsider it just once more but I know its not fun switching libraries "just because" :) Feel free to ignore my notes.

Edited by szabesz
  • Like 1
Link to post
Share on other sites
5 minutes ago, bernhard said:

I have not seen anything that would not be possible using aggrid

Not saying it's a reason to switch, but it does support xlsx whereas that appears to require the paid version aggrid.

  • Like 1
Link to post
Share on other sites

Thanks for your feedback, I really enjoy the discussion.


Aggrid is also mit licensed: https://github.com/ag-grid/ag-grid/blob/master/LICENSE.txt

And I don't think it's bad to have paid pro features. Quite on the contrary. I think it can ensure a long life of the software and good quality. We know that principle from somewhere, don't we?! 😉


I have looked at this closely already as it is a must for me to transfer data to excel. Aggrid has the ability to export data as CSV with custom separators. It's perfectly fine to use this for excel export IMHO. It even has custom renderers that only fire when data is accessed for export. Only thing missing at CSV compared to xlsx is fancy styling and formulas etc. Personally I don't need this in any of my projects.

Ok, simple links come to my mind. That might be nice to have. But we can still use the API to get data and then use any other JavaScript xlsx library to create our files. Or just pay a little fee to enable that feature.


Aggrid looks really well crafted. I'm actually quite happy that I forgot my version of datatables at home over Easter so I was forced to take a pause and take a closer look to aggrid 😂

  • Like 1
  • Thanks 1
Link to post
Share on other sites
49 minutes ago, szabesz said:

I have also checked out a lot of these JS table libraries and Tabulator

Thanks for this! A while back (actually, a long time ago), I thought I'd checked them all but it seems there's quite a number of new kids on the block (unless I missed them first time round :)). I would have loved a Pivot Tables feature (aggrid has this in the paid version).

Sorry to hijack your thread Bernhard...

  • Like 1
Link to post
Share on other sites

I think I'm almost done :)

Plugins are now very easy to create and extremely useful as they are reuseable across multiple projects:


Sample setup of column statistics:

  // custom column stats
  grid.plugins.colStats.valueGetters = {
    id: function(column, selected) {
      return grid.pluck(0,{selected}).length + (selected ? ' selected' : ' rows');
    percent: function(column, selected) {
      return grid.avg(column, {selected});

Everything works in the backend and in the frontend, just echo the field as you would do with any other field

echo $page->mygridfield


Data loads blazingly fast. The 10.001 rows here load in 500ms and are automatically compressed by the server to reduce transfer time (here it results in 90KB instead of 1MB of data!). Thx again @adrian for that idea.


Cell renderers can be combined as you like! That's really powerful and great! We can build libraries of different cellRenderers that we need often and then just wrap them in a function and return the one's we like:


In this column I combine the "actionItems" renderer and the "percentBar" renderer. The actionItems are only applied for regular rows. For rows of the "colStats" plugin we only append " (avg)" to the cell and don't show the icons because they are here to edit this lines related page (and of course the statistics row has no related page):

  colDef.cellRenderer = function(params) {
    var str = '';
    if(!params.data.colStatsRowType) {
      str = RockGrid.renderers.actionItems(params, [
          icon: 'fa fa-bolt',
          href: '/admin/page/edit/?id=' + params.data.id,
          target: ' target="_blank"',
          str: 'Open external: ' + params.data.title,
          icon: 'fa fa-search',
          href: '/admin/page/edit/?field=percent&id=' + params.data.id,
          str: 'Open panel: ' + params.data.title,
          class: ' class="pw-panel hover"',
    else {
      str = ' (avg)'
    return RockGrid.renderers.percentBar(params, str, (!params.data.colStatsRowType ? 0 : 2));


Updating the grid after closing the panel is on my todo-list :)

  • Like 6
Link to post
Share on other sites

Just tested the field on a custom admin page:

  public function ___execute() {
    $form = $this->modules->get('InputfieldForm');

    $f = $this->modules->get('InputfieldRockGrid');
    $f->label = 'Default Report';
    $f->themeBorder = 'none';
    $f->setData("id>0, limit=10", [

    return $form->render();



Thanks again @adrian for Tracy's awesome request info panel to get the proper "themeBorder" setting :) 

edit: ajax mode does not yet work in processmodules...

  • Like 2
Link to post
Share on other sites

Question to all of you: At the moment the module loads all assets separately. Each plugin and each renderer is placed in one file. I don't want to change this, because that way it stays clean and maintainable. But I thought it might not be ideal to load all those files separately for sometimes only one line of code inside this file. Do you have any ideas how i could combine those files to one js file and one css file? ProCache could do that on the frontend, but I don't want to rely on a pro module, and it would not work in the backend.

Thanks for any hints


Link to post
Share on other sites
2 hours ago, bernhard said:

Do you have any ideas how i could combine those files to one js file and one css file?

Maybe you could provide a Gulp tasks file along the module which could be called and generate a rockdatatables.min.js/css.


  • Like 1
Link to post
Share on other sites
Just now, adrian said:

Hey @bernhard - totally OT, but any ideas why the full Tracy bar is showing twice in your screenshot?

I knew you would ask :D Thats the screenshot tool ;)

26 minutes ago, flydev said:

Maybe you could provide a Gulp tasks file along the module which could be called and generate a rockdatatables.min.js/css.

Hm, never worked with gulp and don't think it would be worth the effort. Maybe it does not matter at all? Does anybody know of any real issues when loading a lot of files? Does anybody know at which number this "a lot" could be?

I thought of a snippet that does a foreach and creates a file on the fly with file_put_contents. But the file would need to be different for all pages (thats how it works now). Hm... I could actually change that behaviour and create one single js and one single css file thats always loaded when any rockgrid item is available on the page. Since all the plugins load with eventlisteners this should work...

I'll leave this on the ideas-list...

  • Like 1
Link to post
Share on other sites
2 minutes ago, jmartsch said:

@bernhard You could use the AIOM Module for this, it should also work in the backend. Please look at the sections "minify Javascript" and "Conditional loading". You can even parse LESS files with it. But who needs LESS, when you have SASS? Oooops, I didn't say anything ;) 

Thx. But I don't want to add any dependencies if not really necessary (like RockSqlFinder)

Link to post
Share on other sites
1 hour ago, bernhard said:

Hm, never worked with gulp and don't think it would be worth the effort. Maybe it does not matter at all? Does anybody know of any real issues when loading a lot of files? Does anybody know at which number this "a lot" could be?


Multiple files would be multiple HTTP Requests which would take a longer time, than loading one large file. There are some readings what is "a lot" and if you stay under 14KB you can do the whole file in one roundtrip. Don't know if this is correct, but this is something I remember.

Don't know if this still is relevant with HTTP 2.

Link to post
Share on other sites

Ok, here you go. It's simple.

Create two files in your root directory


var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var gulp = require('gulp');

var jsFiles = 'lib/**/*.js',
    jsDest = 'dist/';

gulp.task('scripts', function() {
   return gulp.src(jsFiles)

gulp.task('default', ['scripts']);

Please change the paths to your javascript files according to your needs.

In my example every .js file under "lib" and its subdirectories are catched.

You can also change the jsDest. This is where the concatenated file "scripts.js" will be stored.

Create a package.json

  "name": "gulp-simple-concat",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.1",
    "gulp-uglify": "^3.0.0"

Then run

npm install

Node.js has to be installed for this to work. But it is very common now for web-devs to have this installed.

When npm is finished, just run `gulp`in your console/terminal.

That's it. Now you have a concatenated and minified javascript file.


  • Like 1
Link to post
Share on other sites
15 hours ago, bernhard said:

Does anybody know of any real issues when loading a lot of files? Does anybody know at which number this "a lot" could be?

If I were you, I would not put too much effort in it – as we are talking about the backend – but if you want to learn Gulp then why not? ;) Soon it is http2 time and as far as I can remember I read that when using http2 merging assets into one is often the wrong choice. But even with http1, since files are cached by the browser you loose a few millisecs first, that's all I guess.

I have seen WP sites with about a hundred js/css files loaded separately but the real issue with page load  speed never seemed to be loading those but mostly other bottlenecks are at play.

Of course, I biased, just read my current motto:
"It is unwise to relentlessly chase performance at the expense of everything else. Better is the enemy of good!"


Link to post
Share on other sites

I wouldn't bother with that neither. Perhaps you could set up a js loader (eg. Require.js) that would load all the js files but I think that's also unnecessary.

  • Like 1
Link to post
Share on other sites

Thanks @szabesz and @tpr, same feeling here. I just thought there might be a processwireish-3-lines-of-code-no-dependencies-at-all solution ;) 

Also thanks @jmartsch, but the last thing i want is to include any dependencies for such a small priority :) 

Thanks for your feedback.

  • Like 2
Link to post
Share on other sites

I don't want to pollute your official thread so I post here.

Perhaps you have an idea before I go further in my questions :)

I have a template which contain some fields. Two of them are timestamp, rest are integer.

What I want is to fetch pages that are in a date range, so I have this selector : 


has_parent=734756, template=transaction, range=(date>=1514761200, date<=1523483999), montant_especes=0, montant_carte_bancaire=0, montant_cheques=0

In this example, the system fetch 18119 pages. Results :



$this->pages->findIDs($selector); // 9387.67ms, 0.04 MB

$this->pages->findMany($selector); // 10494.93ms, 0.29 MB

$this->pages->findObjects($selector, ['title']); // 12259.55ms, 0.56 MB


It take around 10 seconds to fetch all pages, in the DBMS it take 0.3908 second(s) for 18119 pages.

I think I am missing something :undecided:

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By monollonom
      (once again I was surprised to see a work of mine pop up in the newsletter, this time without even listing the module on PW modules website 😅. Thx @teppo !)
      Github: https://github.com/romaincazier/FieldtypeQRCode
      Modules directory: https://processwire.com/modules/fieldtype-qrcode/
      This is a simple module I made so a client could quickly grab a QR Code of the page's url in the admin.
      There's not much to it for now, but if need be you can output anything using a hook:
      $wire->addHookAfter("FieldtypeQRCode::getQRText", function($event) { $event->return = "Your custom text"; }) You can also output the QR code on your front-end by calling the field:
      echo $page->qr_code_field; The module uses the PHP library QR Code Generator by Kazuhiko Arase. When looking for a way to generate a QR Code in PW I came across @ryan's integration in his TFA module. I'm not very familiar with fieldtype/inputfield module development so I blindly followed @bernhard (great) tutorial and his BaseFieldtypeRuntime. At some point I'll take a deeper look to make a module on my own.
      Some ideas for improvements :
      add the ability to choose what to ouput : page's url / editUrl / file(s) / image(s) / ... allow to output multiple QR codes ?
    • By Chris Bennett
      Inspired by @bernhard's excellent work on the new customisable LESS CSS getting rolled into the core soon, I thought I would offer up the module for beta testing, if it is of interest to anyone.

      It takes a different approach to admin styling, basically using the Cascade part of CSS to over-ride default UiKit values.
      Values are stored in ModuleConfig Module creates a separate AdminThemeTweaker Folder at root, so it can link to AdminThemeTweaker.php as CSS AdminThemeTweaker.php reads the module values, constructs the CSS variables then includes the CSS framework Can be switched on and off with a click. Uninstall removes everything, thanks to bernhard's wonderful remove dir & contents function.
      It won't touch your core. It won't care if stuff is upgraded. You won't need to compile anything and you don't need to touch CSS unless you want to.

      It won't do much at all apart from read some values from your module config, work out the right CSS variables to use (auto contrast based on selected backgrounds) and throw it on your screen.
      You can configure a lot of stuff, leave it as it comes (dark and curvy), change two main colors (background and content background) or delve deep to configure custom margins, height of mastheads, and all manner of silly stuff I never use.

      Have been developing it for somewhere around 2 years now. It has been (and will continue to be) constantly tweaked over that time, as I click on something and find something else to do.
      That said, it is pretty solid and has been in constant use as my sole Admin styling option for all of those 2 years.

      If nothing else, it would be great if it can provide any assistance to @bernhard or other contributor's who may be looking to solve some of the quirkier UiKit behavior.
      Has (in my opinion) more robust and predictable handling of hidden Inputfields, data-colwidths and showIf wrappers.
      I am very keen to help out with that stuff in any way I can, though LESS (and any css frameworks/tools basically) are not my go.
      I love CSS variables and banging-rocks-together, no-dependency CSS you can write with notepad.


    • By opalepatrick
      I see old posts saying that repeaters are not the way to go in Custom Process Modules. If that is the case, when using forms (as I am trying to do) how would one tackle things like repeat contact fields where there can be multiple requirements for contact details with different parameters? (Like point of contact, director, etc) or even telephone numbers that have different uses?
      Just for background I am creating a process module that allows me to create types of financial applications in the admin area (no need to publish any of this, pure admin) that require a lot of personal or company information.
      Maybe I am thinking about this incorrectly?
    • By HMCB
      I ran across a reference to IftRunner module. The post was 6 years ago. I cant find it in available modules. Has it been pulled?
    • By tcnet
      PageViewStatistic for ProcessWire is a module to log page visits of the CMS. The records including some basic information like IP-address, browser, operating system, requested page and originate page. Please note that this module doesn't claim to be the best or most accurate.
      One of the biggest advantage is that this module doesn't require any external service like Google Analytics or similar. You don't have to modify your templates either. There is also no Javascript or image required.
      There is only one disadvantage. This module doesn't record visits if the browser loads the page from its browser cache. To prevent the browser from loading the page from its cache, add the following meta tags to the header of your page:
      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> How to use
      The records can be accessed via the Setup-menu of the CMS backend. The first dropdown control changes the view mode.

      Detailed records
      View mode "Detailed records" shows all visits of the selected day individually with IP-address, browser, operating system, requested page and originate page. Click the update button to see new added records.

      Cached visitor records
      View modes other than "Detailed records" are cached visitor counts which will be collected on a daily basis from the detailed records. This procedure ensures a faster display even with a large number of data records. Another advantage is that the detailed records can be deleted while the cache remains. The cache can be updated manually or automatically in a specified time period. Multiple visits from the same IP address on the same day are counted as a single visitor.

      Upgrade from older versions
      Cached visitor counts is new in version 1.0.8. If you just upgraded from an older version you might expire a delay or even an error 500 if you display cached visitor counts. The reason for this is that the cache has to be created from the records. This can take longer if your database contains many records. Sometimes it might hit the maximally execution time. Don't worry about that and keep reloading the page until the cache is completely created.
      Special Feature
      PageViewStatistic for ProcessWire can record the time a visitor viewed the page. This feature is deactivated by default. To activate open the module configuration page and activate "Record view time". If activated you will find a new column "S." in the records which means the time of view in seconds. With every page request, a Javascript code is inserted directly after the <body> tag. Every time the visitor switches to another tab or closes the tab, this script reports the number of seconds the tab was visible. The initial page request is recorded only as a hyphen (-).

      You can access the module settings by clicking the Configuration button at the bottom of the records page. The settings page is also available in the menu: Modules->Configure->ProcessPageViewStat.
      This module uses the IP2Location database from: http://www.ip2location.com. This database is required to obtain the country from the IP address. IP2Location updates this database at the begin of every month. The settings of ProcessPageViewStat offers the ability to automatically download the database monthly. Please note, that automatically download will not work if your webspace doesn't allow allow_url_fopen.
      This module uses DragScroll. A JavaScript available from: http://github.com/asvd/dragscroll. Dragscroll adds the ability in view mode "Day" to drag the records horizontally with the mouse pointer.
      This module uses the PHP class parseUserAgentStringClass available from: http://www.toms-world.org/blog/parseuseragentstring/. This class is required to filter out the browser type and operating system from the server request.
  • Create New...