Zach’s ugly mug (his face) Zach Leatherman

Problems with YUI DataTable

April 04, 2007

Warning

This article is old and may contain information that is outdated, irrelevant, or—dare I say it—no longer accurate. Read with care!

If you have read anything I’ve written before or know me at all, you know that my go-to JavaScript library is the one and only YUI. So obviously, when I was looking around for a Grid (or as YUI jargon goes, a DataTable), naturally I’m going to turn to YUI compatible components. First, I looked at Jack Slocum’s EXT, which has a nice looking Grid component that had a lot of features I wouldn’t need, but I didn’t really want to take a 0.5 MB hit for the limited feature set I was requiring. Adding the YUI DataTable would only tack on approximately 70-75 KB of additional download. So first, let me establish what I’m going for:

Minimum Feature Set:

  • Client-Side Sorting: I don’t want it to do an XMLHttpRequest to sort the data, I want it to be done all clientside.
  • Simple inline editing: Edit a field in the table right there on the table. I hadn’t established what types of data I would need to edit yet.
  • Data Sources: load from a native JavaScript array or a XMLHttpRequest returning XML or JSON.
  • Data Type Sort Algorithms: at the very minimum different sorting algorithms for numeric columns and string columns.
  • Hierarchical Columns: group column headers together under a parent header.
  • Easily customizable: must be able to customize the look and feel of the grid easily using CSS and not by editing Javascript.
  • Header Freeze: If I have overflow on my table vertically causing a scroll bar, I want the table headers to remain shown at the top of the table while I scroll from top to bottom.
  • Custom Cell Rendering: I have the data I’m loading, but I want to change how it looks when it is rendered to the table. Common for date formatting.

Luxury Feature Set:

  • Resizeable Columns: change the width of a column by dragging on the column header’s right border.
  • Movable Columns: dragging a column will cause it to be moved on the table (TIBCO General Interface supports this).
  • Custom Sort Algorithm: write my own algorithm to specify how data is sorted, or provide a way to do multi-column sorting (sort within one column, ties are sorted by another column, and so on).
  • Dynamic Paging (don’t make me click numbered links, load the data automatically when I scroll) both on the client (dynamically insert only what I’m looking at and remove what I’ve scrolled past) and using the server (load more data through an XMLHttpRequest)
  • Column Freeze: if the table is going to scroll horizontally, allow the developer to freeze a column or multiple columns so that they are shown when scrolling from left to right.

Evaluation of Options: How does the YUI DataTable stack up?

Basic Items: Client-Side Sorting, Simple inline editing, Data Sources, Data Type Sort Algorithms (stock types not yet implemented out of the box), Hierarchical Columns, Header Freeze (buggy), Custom Cell Rendering, and is easily customizable with CSS.

Luxury Items: Resizeable Columns, Movable Columns (not supported), Custom Sort Algorithms are supported (you can right your own Data Type Sort Algorithms with this feature), Dynamic Paging (manually, not dynamic), Column Freeze (not supported)

Problems:

  • Any sort of fixed width table is going to be problematic. Putting a fixed width on the table causes the table headers to be misaligned with the associated table data. It’s a mess. The only viable option here is to let the table do it’s own width calculations. You can’t even set the column widths manually using the {width} variable as suggested when using a fixed width table.
  • Data Type Sort Algorithms supposedly work from the column type, but this feature is documented in the code as being a TODO. All columns are sorted by a string datatype, meaning that if your column is numeric and you had the following rows: { 3, 7, 40 }, the sort result would be { 3, 40, 7 }.
  • Header Freeze was problematic. Implementing the {scrollable=true} feature as recommended by the documentation causes the table headers to be misaligned with the data in a fixed width table.
  • Paging uses the old school numbers method. This wasn’t a deal breaker, since I classified this feature as a luxury item.

Granted, the DataTable in it’s current form is a beta component, but that 0.5 MB ExtJS hit is looking pretty nice right now.

Minor Update: to do a fixed width table that will overflow horizontally, this is the method you can use:

div#dataTableId { /* change this to whatever id you're using to hold the dataTable /
width:520px; /
put in your own fixed width /
overflow-x:auto;
overflow-y:hidden;
}
.yui-dt-headtext, .yui-dt-headcontainer {
position: static; /
without this declaration, the headers weren't horizontally scrolling with the data in IE6 */
}


Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at IndieWeb Avatar for https://cloudcannon.com/CloudCannon. He is the creator and maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 79 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

28 Comments
  1. Nate Koechley Disqus

    06 Apr 2007
    Thank you for checking out the beta release of the DataTable (and for your nice words about YUI in general!). Feedback like yours is critical to the library and exactly why we make these early betas available. We appreciate you taking the time, and we're listening.You've touched on a few issues which I'll address in order:issues with sorting;issues with fixed widths, resizable columns and scrolling ("header freeze");and issues with rearrangable columns and endless scrolling (pagination) features.Regarding sorting, DataTable currently sorts strings, numbers, and dates, but only when the values are already those types in JavaScript. In contrast, if you get values over the wire (<abbr title="XMLHttpRequest">XHR</abbr>), DataTable will treat all values as strings in those cases. As a workaround, you could implement a custom sort function to do the data type conversion. Data parsed from markup will be typed correctly, and so we're a part of the way there; before we get out of beta we plan to provide a mechanism so a value can be treated as a specific type regardless of its origin. I can tell you that in the next release (coming soon) we'll have a hook for you to do your own conversion of data coming over <abbr title="XMLHttpRequest">XHR</abbr>, and in the subsequent release it will do a lot of conversions for you out of the box and also provide a mechanism for you to do more sophisticated custom conversions.Column widths, table widths, resizability, and scrolling features all work when used individually, but have problems (as you documented) when used together. By initially focusing on each feature in isolation, we can refine and optimize architecture and APIs with the most freedom. This leeway is important during a true pre-release beta period. Before we come out of beta we'll have a cohesive feature set.The third class of features you mentioned includes endless scrolling (dynamic pagination) and rearrangable columns. These aren't self-contained DataTable features but rather collaborations with other YUI utilities. For example the DragDrop utility will enable columns to be reordered. Before we wire up these higher-order features we hope to stabilize DataTable itself. Look for these two features (and a few others) post-beta. We'll try to do a better job communicating plans like this in the future.Again, thank you sincerely for helping improve the YUI library. We're definitely listening to you and the entire community.Thanks,Nate
  2. admin Disqus

    10 Apr 2007
    Thanks for the reply Nate. In the documentation regarding sorting, there is a type attribute you can set on the column headers. I had assumed that this would cast your variable into the appropriate type prior to sorting. Good to know that it respects the native types for now.I did decide to stick with the lightweight YUI grid for my project, and it is working pretty well so far. It will be nice to see when you guys get all the kinks worked out.PS: I saw your talk at AjaxWorld last October, I learned some good stuff about Yahoo's client side development practices.
  3. Zach Leatherman Disqus

    19 Apr 2007
    Just for those visiting the page to read about the DataTable, this article was written with respect to YUI version 2.2.0, and I have yet to test some of the features above with the newer versions. If you've proven some of the above wrong, please post a correction in the comments.
  4. Tamilselvan Disqus

    17 May 2007
    Hi, I'm a beginner in YUI. Currently i'm trying to use the YUI data table in our new project. My requirement is after populating data table, each table row has a edit button or hiberlink to edit the particulate row in a table, say customer details for example.I'm not able to add a button for each row. could you guide me how to do it in YUI?thanks in advance,Tamil.
  5. Zach Leatherman Disqus

    31 May 2007
    Sure, you can do that with the DataTable.http://developer.yahoo.com/...Custom Formatters allow you to modify the HTML inside a column. Use that in combination with the Section on 'Inline Editing.'
  6. Seng Kai Disqus

    21 Jun 2007
    Hi I wonder if anybody could help me with my project.I have two problems here which I face. As i'm new to using Ajax technology there's a lot of stuff that i need to know.My problem is that I would like to add a row to an existing table populated using XML. I had the table populated but I would like to add a new row to this table which I'm not sure how i could do it.My next problem is as the incline editing in YUI show, how can i read in the value after the user have edited the field so that I could update my database?Thanks a lot. Really much appreciate those who can guide me along. Thanks
  7. Zach Leatherman Disqus

    22 Jun 2007
    Let's just do one at a time here. Are you trying to add a node into your source XML, or are you just trying to add a row into your HTML table?
  8. Seng Kai Disqus

    26 Jun 2007
    i'm trying to do something like spreadsheet like of style.When the user click on add new row.A new row would be added onto the existing table after which the user would click on a button let's say commit and it would add to the database.
  9. Matt Howey Disqus

    12 Jul 2007
    Tamilselvan: regarding your "each table row has a edit button" - I'm sure by now you've figured out how to do this, but I thought I would offer a solution that I find to work well. Setup row highlighting, put a subscription to the click event and a keylistener for the [enter] key, then perhaps you could edit in a YUI panel or something. As long as you are listening for a doubleclick and enter, you'll be able to implement this. Then when done editing, close the panel and return focus to the datatable....
  10. Pankaj Disqus

    24 Jul 2007
    Hi,can you please provide me an example, in which paging is implemented and on every click the data comes from the database rather than just a simple data.js file
  11. Zach Leatherman Disqus

    26 Jul 2007
    Hey Pankaj, that sounds like a better question for the YUI Developer Mailing List.http://tech.groups.yahoo.co...Sounds like your use case is possible. Have you looked at the examples describing XHR for the DataTable?http://developer.yahoo.com/...
  12. Shafique Disqus

    02 Oct 2007
    I've noticed that when implementing a custom sort method, and setting "sortable: true" on the columns I wanted sortable, and explicitly setting "sortable: false" on the columns that CANNOT be sorted, i am allowed to click ANY column head and the table will refresh! Those columns with sortable: true make a nice hand-pointer and a tooltip, while those with sortable: false are a non-clickable arrow (which is in fact clickable). Is this bug being addressed?
  13. Zach Leatherman Disqus

    07 Oct 2007
    Sounds like you need to head over to the bug tracker:http://sourceforge.net/trac...
  14. sirjon Disqus

    07 May 2008
    Hi ,I want to add the drop-down in the YUI panel header.Please help as I am completeley stuck on this.
  15. Khushbu Disqus

    09 Sep 2008
    How do I display data dynamically into my datatable using type_json or type_xml? I can not find any good example.
  16. Zach Leatherman Disqus

    09 Sep 2008
    Hey sirjon and Khushbu,You're much better off trying the YUI mailing list located here: http://tech.groups.yahoo.co...Thanks!Zach
  17. Datatable sort on one column o Disqus

    25 Feb 2009
    Hi, I have problem to enable sorting on more than one column (the last column defined in myColumnDef) in YUI datatable. Could anybody find out the error in my code?Here is my code: YAHOO.util.Event.addListener(window, "load", function() { YAHOO.example.MultipleFeatures = function() { var i=0; var data = new Array(); data[i++] = {title: "", lastChangedBy:"" }; var myColumnDefs = [ {key:"lastChangedBy", label: "Updated Person",sortable:true, resizeable:true}, {key:"title", label: "Asset Group Name", sortable:true, resizeable:true} ]; /* This is where we set up the DataTable */ var myDataSource = new YAHOO.util.DataSource(data); myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY; myDataSource.responseSchema = { fields: [{key:"lastChangedBy"},{key:"title"} ]}; // Here is where we configure the pagination of the table. If the users want this, just flip flag to true var myConfigs = { paginator : new YAHOO.widget.Paginator({ rowsPerPage : 10 }) }; var myDataTable = new YAHOO.widget.DataTable("basic", myColumnDefs, myDataSource, myConfigs); return { oDS: myDataSource, oDT: myDataTable }; }(); });
  18. Abhishek Disqus

    08 Mar 2009
    hi , I aM USinG T:DatatABlE , MY rEqUIRmeNT Is i Need to sHow remOVe LINK in The LASt ColUmn But lasT ColuMn NEed noT To haVE hEAdEr In That But firST tWO Col sHOULd havE heADeR , wHen i Am UsING faCeT in aNy oF The COlumN jSf AUTOmAtICaLLy cRaTeD Th FOR EAcH COumn. CNa YOU heLP ? I used tO heAdeRsTyLeclass WHIcH iS aSSOciaTED wIth T:coLumn stIlL NO LUck. cAn I OveRRiDe COluMN headeR CLASs ??
  19. Zach Leatherman Disqus

    08 Mar 2009
    Hey guys, these types of technical support questions should be posted on the YUI mailing list. You'll get the best response over there.http://tech.groups.yahoo.com/group/ydn-javascript/Thanks,Zach
  20. Edward Disqus

    27 Jul 2009
    HAlLo, pLEASE HeLP Me. I COuLd NOt ReloAd rIght THE dATAsOurCe of THe DaTatAblE comPonEnt. ThE dAtASoURCE I GEt FROM MYSql. wHEn I wAnt to ReFrEsH mY dAta (pRevIousLY cHaNge SOME dATa INTo tHE baSE) uSiNG mETHods aBOve Or just by ReLOadIng The paGe (F5), nOTHIG WaS HaPPEn. i hAVE ToOk INto aCouNt tHAT WhEn I ClIck To tHe FiEld FOr SORTING: iN oNe DiRECtIon It ShOw RIght ReSuLt...In ANoTheR - OLd liSt Of DaTa...thIS IS MY COdE:// cODe EXAMPLEYAhOO.exAmplE.dyNaMIcdatA = FuNCtiON() { // CoLUMn DEFinitIONs VaR MYcoLUmNDefS = [ // SOrtABlE:trUe eNABLEs SOrTiNG {kEY:"iD", LabEL:"Id", soRTAbLe:tRue}, {KEY:"dAtE", Label:"date", SORtABLe:TRUe}, {KEY:"timE", LABEl:"tIMe" /*, fORmATTER:"DAte"*/ }, {Key:"TOtAlCHARgE", LAbeL:"TOtalcHarGe", sOrTaBle:true},{KEy:"TotalEneRGY", lAbeL:"TOTaLEnERGy", SoRtaBLe:true},{kEy:"maXPEAK", laBel:"MAXPeAk", SORtaBLe:TrUE},{kEy:"NUmBOfSTROKES", laBEl:"NUMbOfStroKEs", SorTabLE:tRuE}, {kEY:"JPgiD", laBEL:"jpgId", SoRTABle:True} ]; // cUsToM PaRser VAR StRINgTodaTe = FUNCtIOn(SDATA) { VaR ARray = sdaTa.SpLit("-"); rETURn new DatE(aRRaY[1] + " " + ArrAy[0] + ", " + aRraY[2]); }; // dataSoURCE iNstAncE VaR MYDatAsOurCE = New Yahoo.UTil.DAtaSoUrCE("JSON_proXy.phP?"); mydaTaSourCe.rEsPoNSEtype = yahoo.UtiL.DaTAsOuRce.tyPe_JsON; MydATAsoUrCe.REsponSescheMa = { RESULTSlISt: "REcords", fiElDs: [{Key:"Id", pARser:"nUmbeR"},{KeY:"daTe"},{keY:"TIme" /*pARSer:stRInGtoDAte*/ },{KeY:"TOtALChArGE",PArseR:"NuMber"},{KEy:"ToTALENergy",pARseR:"NumBer"},{kEY:"MaXpEAk",PaRSER:"NuMBER"},{KEy:"nuMBOfSTROkES",pARser:"NumbEr"},{KEy:"jpgId"} ], meTaFiElds: { toTalReCords: "tOtALreCOrdS" // ACCeSS TO vAlUe In THe sErvEr ReSpoNse } }; // DAtAtABLE CoNfiGUraTION Var MYcoNfIGs = { initIaLReqUesT: "SoRt=id&aMp;Dir=aSC&aMP;sTArtINdeX=0&Amp;RESulTS=25", // IniTiAL ReQUeSt FoR FIRST paGe OF DAta DynaMicdaTa: True, // EnabLeS dynAmic SErVEr-driVEN dAta SoRteDBy : {KeY:"iD", Dir:YAhoO.widGet.dataTaBLE.cLaSs_Asc}, // SETS ui iNITiAL SorT arRoW pAGinATOR: nEW Yahoo.WiDgeT.paGINator({ rOwSPeRPage:25 }) // enaBlEs pAGInaTION }; // daTatABle INSTancE VaR MYdAtAtaBlE = NEw YahOo.wiDGET.daTAtABLE("dyNAMicDatA", MycOlUmnDEFS, mydATASouRCe, mYCoNFigS); // uPdATe totAlrecOrDs On the FLY WiTH vALUE FroM sErvER MyDaTAtaBlE.HaNdLEdAtARetuRnPAyLOaD = functIoN(oreQUESt, oResPOnsE, oPayLoad) { oPAYLOad.totalREcoRds = OrEsPonse.MEta.ToTALRECoRDs; RETURN OpaYloAD; } reTUrN { ds: mYdATASourCe, DT: MYdaTaTAbLE };}();PLeasE aNYoNE EXpLaIn What aND wherE I mUST PuT a code FOR REfreshINgS? tHAnk'S.
  21. Ansar Disqus

    02 Aug 2009
    hiii,i have a problem with my datatable.my datatable updates its content every 5 seconds, but on updating the client-side sorting modified by the user gets reset to server default.i want the sort key the client sets to be set even after data refresh.If u have a solution please help me.This is the codeYUI Library Examples: DataTable Control: Basic Example/* custom styles for this example */.yui-skin-sam .yui-dt-liner { white-space:nowrap; }/* Remove row striping, column borders, and sort highlighting *//* .yui-skin-sam tr.yui-dt-odd,.yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam tr.yui-dt-odd td.yui-dt-desc,.yui-skin-sam tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam tr.yui-dt-even td.yui-dt-desc { background-color: #fff;}*/.yui-skin-sam .yui-dt tbody td { border-bottom: 1px solid #fff;}.yui-skin-sam .yui-dt thead th { border-bottom: 1px solid #7f7f7f;}.yui-skin-sam .yui-dt tr.yui-dt-last td,.yui-skin-sam .yui-dt th,.yui-skin-sam .yui-dt td { border: none;}/* Class for marked rows */.yui-skin-sam .yui-dt tr.mark td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.mark td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.mark td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.mark td.yui-dt0-col-Price { background-color: #891010; color: #fff;}.yui-skin-sam .yui-dt tr.m td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.m td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.m td.yui-dt0-col-Price,.yui-skin-sam .yui-dt tr.m td.yui-dt0-col-Price { background-color: #108918; color: #fff;}var Dom = YAHOO.util.Dom; YAHOO.util.Event.addListener(window, "load", function() { YAHOO.example.XHR_Text = function() { var myColumnDefs = [ {key:"Stock", sortable:true, resizeable:true},{key:"Price", sortable:true, resizeable:true}, {key:"Per.Change", label:"%Change", sortable:true, resizeable:true}, {key:"Change", sortable:true, resizeable:true}, {key:"High", sortable:true, resizeable:true},{key:"Low", sortable:true, resizeable:true}, {key:"Volume", sortable:true, resizeable:true} ]; myDataSource = new YAHOO.util.DataSource("assets/js/price1.txt"); myDataSource.responseType = YAHOO.util.DataSource.TYPE_TEXT; myDataSource.responseSchema = { recordDelim: "|;", fieldDelim: ";", fields: [{key:"Stock", parser:"string"}, {key:"Price", parser:"number"}, {key:"Volume"}, {key:"Per.Change", parser:"number"},{key:"Change", parser:"number"}, {key:"High", parser:"number"}, {key:"Low", parser:"number"} ] };var myRowFormatter = function(elTr, oRecord) { if (oRecord.getData("Price") 640) { Dom.addClass(elTr, 'm'); } return true;}; myDataTable = new YAHOO.widget.DataTable("basic", myColumnDefs, myDataSource, {caption:"MarketWatch", formatRow: myRowFormatter, draggableColumns:true }); // Subscribe to events for row selection myDataTable.subscribe("rowMouseoverEvent", myDataTable.onEventHighlightRow); myDataTable.subscribe("rowMouseoutEvent", myDataTable.onEventUnhighlightRow); myDataTable.subscribe("rowClickEvent", myDataTable.onEventSelectRow); // Programmatically select the first row myDataTable.selectRow(myDataTable.getTrEl(0)); // Programmatically bring focus to the instance so arrow selection works immediately myDataTable.focus(); var myCallback = { success: myDataTable.onDataReturnSetRows, scope: myDataTable, failure: function() { YAHOO.log("Polling failure", "error"); } } myDataSource.setInterval(5000,null, myCallback) return { oDS: myDataSource, oDT: myDataTable }; }();});
  22. Keesjan Deelstra Disqus

    10 Sep 2009
    Hi Zach,readint this post about (old) YUI datatable limitations. I was searching google for "yui datatable headers tooltips". And thats excactly what I want to complete.Do you now of ways to achieve that?I want to make question icons in each header to make help tooltips. Hope you are still 'into' YUI....
    1. Zach Leatherman Disqus

      11 Sep 2009
      Hey Keesjan,Again, I think the best way to get help is on the YUI mailing lists. As far as I know, they're still active!Thanks,Zach
  23. Chi Disqus

    27 Oct 2009
    Hi,I am currently also looking into the "column freeze" feature you talked about ("if the table is going to scroll horizontally, allow the developer to freeze a column or multiple columns so that they are shown when scrolling from left to right.")Do you know if it is doable with the current YUI version, or any possible workarounds?Thanks,Chi
  24. Zach Leatherman Disqus

    31 Oct 2009
    Are you sure horizontal scrolling is necessary for your use case?Usability above precedence.http://www.useit.com/alertb...
  25. Chi Disqus

    04 Nov 2009
    Thank you Zach for that tip! Ya, seems like they don't want the horizontal scrollbar anymore now :)
  26. Mits Disqus

    20 Nov 2009
    hI ZaCh,1) i HaVe cREaTED A tABle WITH ONE roW NEsTED InSIDe a CoLUMN OF The dATa tABLe.uSer Can INsErT and DeLETe ROws In tHe TABle (As i HavE ProvIdeD tHoSE optioNs In MeNu).PrObLEm: If i sELEct MULtIpLe RowS , I Am Not Able TO fETcH The dATA of ThE tABlE (whicH Is nEStED wIThiN a oLuMn).plEASE Tell ME HOW CaN i ACCEsS THe datA In THE taBLe NESTeD WitHin The cOluMN oF a DAtAtABle.WHEn MUlTiple ROWS ARE SElECTeD.2) if have uSEd tHE FunCtIoNs uPdatEROW() Or updATERecorDs() For PasTinG THE daTa froM ONE Row INTo AnOther. THE prOBLEm OF USing THeSe functIONs IN PaSTE OPTION iS ThAt tHESE Two fUNCTioNs uPdATE THE RoW Of tHE datAtAbLe but iT AlSO keEp UpDatING THe rowS EvEn whEN i MakE chaNGEs in thE COpied row lATEr.PLEasE HeLp Me On thIs uRGENtLyTHaNKs IN advAnce :)
  27. Rudi Disqus

    19 Feb 2011
    Hi Zach, Nice article. Thanks for sharing. Do you happen to know how I can refresh a YUI datatable from the code? not using a subscribe to an event. I have code to do a requery that works fine. However, I also have code to perform a database update on a click. I would like to refresh the datatable contents after that database update. Thanks in advance.Best regards,Rudi
Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)