Loading ...
Sorry, an error occurred while loading the content.

Passing dynamic data to a datatable formatter?

Expand Messages
  • htrla57
    In a relatively complex YUI application I have several datatables showing information fetched from the server. These datatables are created and updated by a
    Message 1 of 7 , Jul 1, 2009
    • 0 Attachment
      In a relatively complex YUI application I have several datatables showing information fetched from the server. These datatables are created and updated by a single javascript function. Cell formatting is complex and done by a custom formatter. Same entries may end up in different datatables, and I need to pass one or two parameters to the formatter so that

      a) ids generated are unique
      b) links and ajax requests from within the cell have these correct parameters

      These parameters are not naturally part of the data itself.

      The problem appears to be that although I can handle the creation and update of a number of separate datatables using a single javascript function, the datatables all share the same formatter and I seem to be unable to give context-dependent paramaters to it. So when I do for each datatable created:

      var coldefs = [{key:'deadline', formatter:"tdLineCustom", ... }... ] ;
      YAHOO.widget.DataTable.Formatter.tdLineCustom = tdLineFormatter ;

      function tdLineFormatter(el, oR, oC, oD) {
      tdFormatter(el, oR, oD, ctx, tid) ;
      }

      when I then later update a table by

      tbl.getRecordSet().replaceRecords (obj);
      tbl.render();

      tdFormatter does not get the current values for ctx and tid, but the values from the last datatable created.

      Any ideas?
    • Satyam
      There are two ways to work with the DataTable to provide interactivity to the user. One is to assemble the DataTable with plenty of links with long hrefs full
      Message 2 of 7 , Jul 1, 2009
      • 0 Attachment
        There are two ways to work with the DataTable to provide interactivity
        to the user. One is to assemble the DataTable with plenty of links with
        long hrefs full of URL arguments and action hrefs of the "javascript:
        ..." type. The other is to keep the DataTable simple and do all the
        work on the return. From your message, since you mention complex
        formatters with links and ajax requests, I have the feeling you have
        opted for the first. As I learned myself the hard way, that is not the
        best way, not by a long shot.

        It is best to keep the DataTable simple and use it to display the
        required information to the user. You can also use the RecordSet object
        to store information from extra fields which the user doesn't need to
        see. Even though the information is not show, you can use Record method
        getData() to pick it.

        What you then do is respond to clickevents, either linkClickEvent,
        cellClickEvent or whatever clickable element you provide in the cell. I
        usually respond to cellClickEvent since, if I later decide to change an
        actual <button> element for a background image on the cell (which is
        what I actually use) or change a link for a simple text decorated to
        look as a link, my code won't change. You see, clickEvents bubble so a
        linkClickEvent or buttonClickEvent will bubble to a cellClickEvent (if
        not stopped) and that will bubble to a rowClickEvent and that one to a
        tableClickEvent so I just catch them at the cellClickEvent level and I
        am free to change the look of the cells without changing the code. So,
        then, I have:

        myDataTable.on('cellClickEvent', function (oArgs) {

        var target = oArgs.target,
        record = this.getRecord(target),
        column= this.getColumn(target);
        switch (column.key) {
        }
        }
        });

        So, from the column I can figure out which cell was clicked via its key
        property and then branch of to handle each column separately, from the
        Record object I can read any value, visible or not. If you can built a
        link up front, you must be able to build a link at the back end as
        well. Since you have to set this listener for each DataTable instance
        separately, your question of how identify each table in the formatter so
        as to encode it within the link makes no sense, you don't need to know
        it any longer.

        This mechanism is much faster. It reduces the DOM objects, which is
        crucial in some browsers, it lets the table build faster and if any work
        has to be done it is only than when required. What's the point of
        assembling hundreds of links that won't be clicked? Build them when they
        are clicked! And gain the flexibility of putting links, buttons, images
        or decorated text in your cells without changing your code, keeping the
        visual design aspect independent of the code.

        Now, I just hope I just got it right, I mean, my assumption of what you
        are trying to do, otherwise, my apologies for wasting your time.

        Satyam


        htrla57 escribió:
        > In a relatively complex YUI application I have several datatables showing information fetched from the server. These datatables are created and updated by a single javascript function. Cell formatting is complex and done by a custom formatter. Same entries may end up in different datatables, and I need to pass one or two parameters to the formatter so that
        >
        > a) ids generated are unique
        > b) links and ajax requests from within the cell have these correct parameters
        >
        > These parameters are not naturally part of the data itself.
        >
        > The problem appears to be that although I can handle the creation and update of a number of separate datatables using a single javascript function, the datatables all share the same formatter and I seem to be unable to give context-dependent paramaters to it. So when I do for each datatable created:
        >
        > var coldefs = [{key:'deadline', formatter:"tdLineCustom", ... }... ] ;
        > YAHOO.widget.DataTable.Formatter.tdLineCustom = tdLineFormatter ;
        >
        > function tdLineFormatter(el, oR, oC, oD) {
        > tdFormatter(el, oR, oD, ctx, tid) ;
        > }
        >
        > when I then later update a table by
        >
        > tbl.getRecordSet().replaceRecords (obj);
        > tbl.render();
        >
        > tdFormatter does not get the current values for ctx and tid, but the values from the last datatable created.
        >
        > Any ideas?
        >
        >
        >
        >
        > ------------------------------------
        >
        > Yahoo! Groups Links
        >
        >
        >
        > ------------------------------------------------------------------------
        >
        >
        > No virus found in this incoming message.
        > Checked by AVG - www.avg.com
        > Version: 8.5.375 / Virus Database: 270.13.1/2211 - Release Date: 06/30/09 11:37:00
        >
        >
      • htrla57
        ... Satyam Thank you for your contribution. However, I already have everything working satisfactorily, except that I need to pass parameters to my custom
        Message 3 of 7 , Jul 1, 2009
        • 0 Attachment
          --- In ydn-javascript@yahoogroups.com, Satyam <satyam@...> wrote:
          > It is best to keep the DataTable simple and use it to display the
          > required information to the user. You can also use the RecordSet object
          > to store information from extra fields which the user doesn't need to
          > see. Even though the information is not show, you can use Record method
          > getData() to pick it.
          >...
          >
          > Now, I just hope I just got it right, I mean, my assumption of what you
          > are trying to do, otherwise, my apologies for wasting your time.
          >
          > Satyam
          >

          Satyam

          Thank you for your contribution. However, I already have everything working satisfactorily, except that I need to pass parameters to my custom formatter which are not in the Record Row and which do not come from the server. In a way, each copy of the datatable has its own context defined by these parameters, and the formatter would need to know this. So far my attempts to accomplish this have failed. But perhaps this can be done using metafields in the record set?
        • htrla57
          ... One addition: my current solution to locally loop through the JSON data before it goes to the datasource and add the context data to each record. But the
          Message 4 of 7 , Jul 1, 2009
          • 0 Attachment
            --- In ydn-javascript@yahoogroups.com, "htrla57" <htoyryla@...> wrote:
            > Thank you for your contribution. However, I already have everything working satisfactorily, except that I need to pass parameters to my custom formatter which are not in the Record Row and which do not come from the server. In a way, each copy of the datatable has its own context defined by these parameters, and the formatter would need to know this. So far my attempts to accomplish this have failed. But perhaps this can be done using metafields in the record set?
            >

            One addition: my current solution to locally loop through the JSON data before it goes to the datasource and add the context data to each record. But the data is the same for each record in a table so I regard this as a temporary quick fix.
          • htrla57
            ... A further comment on this. My approach is probably somewhere between. There is a context menu on the datatable level. In additon, inside a cell some
            Message 5 of 7 , Jul 1, 2009
            • 0 Attachment
              --- In ydn-javascript@yahoogroups.com, Satyam <satyam@...> wrote:
              >
              > There are two ways to work with the DataTable to provide interactivity
              > to the user. One is to assemble the DataTable with plenty of links with
              > long hrefs full of URL arguments and action hrefs of the "javascript:
              > ..." type. The other is to keep the DataTable simple and do all the
              > work on the return. From your message, since you mention complex
              > formatters with links and ajax requests, I have the feeling you have
              > opted for the first. As I learned myself the hard way, that is not the
              > best way, not by a long shot.
              >

              A further comment on this. My approach is probably somewhere between. There is a context menu on the datatable level. In additon, inside a cell some elements have event handlers. These event handlers are attached by the custom formatter. It does not really look complex to the end user, it does not even look like a table :-)

              But the formatter needs to know its context (which is table specific) in order to pass this information to the event handlers and in order to implement a specific way of assigning ids to elements within the cell.

              I have a function to build/update a datatable based on a javascript object. This function is used to support multiple datatables under different tabs, and the context is defined by two parameters: ctx and tid.

              parseDataIntoTable(o, ctx, tid) {

              Within this function, if the table does not yet exist, it is created and populated based on the data, context menu is created and the custom formatter is assigned.

              If the table exists, it is updated with the new data. At this point, I get into problems as my custom formatter does not use the current values for ctx and tid, but those that were valid when the custom formatter was last assigned.

              This is how I have tried to prevent ctx and tid being bound at the time when the formatter is assigned, but it did not help.

              YAHOO.widget.DataTable.Formatter.tdLineCustom = tdLineFormatter ;

              function tdLineFormatter(el, oR, oC, oD) {
              tdFormatter(el, oR, oD, ctx, tid) ;
              }

              tdLineFormatter is inside parseDataIntoTable, where ctx and tid have valid values, while tdFormatter is outside for a reason.

              But as I mentioned in a previous posting, perhaps metafields are the way to go.
            • htrla57
              ... I am now trying to solve my problem using metafields in the datasource. However, I cannot find anything in the API to allow the formatter access the
              Message 6 of 7 , Jul 3, 2009
              • 0 Attachment
                --- In ydn-javascript@yahoogroups.com, "htrla57" <htoyryla@...> wrote:
                >
                > A further comment on this. My approach is probably somewhere between. There is a context menu on the datatable level. In additon, inside a cell some elements have event handlers. These event handlers are attached by the custom formatter. It does not really look complex to the end user, it does not even look like a table :-)
                >
                > But the formatter needs to know its context (which is table specific) in order to pass this information to the event handlers and in order to implement a specific way of assigning ids to elements within the cell.
                >
                > I have a function to build/update a datatable based on a javascript object. This function is used to support multiple datatables under different tabs, and the context is defined by two parameters: ctx and tid.
                >
                > parseDataIntoTable(o, ctx, tid) {
                >
                > Within this function, if the table does not yet exist, it is created and populated based on the data, context menu is created and the custom formatter is assigned.
                >
                > If the table exists, it is updated with the new data. At this point, I get into problems as my custom formatter does not use the current values for ctx and tid, but those that were valid when the custom formatter was last assigned.
                >
                > This is how I have tried to prevent ctx and tid being bound at the time when the formatter is assigned, but it did not help.
                >
                > YAHOO.widget.DataTable.Formatter.tdLineCustom = tdLineFormatter ;
                >
                > function tdLineFormatter(el, oR, oC, oD) {
                > tdFormatter(el, oR, oD, ctx, tid) ;
                > }
                >
                > tdLineFormatter is inside parseDataIntoTable, where ctx and tid have valid values, while tdFormatter is outside for a reason.
                >
                > But as I mentioned in a previous posting, perhaps metafields are the way to go.
                >

                I am now trying to solve my problem using metafields in the datasource. However, I cannot find anything in the API to allow the formatter access the metafields. The formatter has the Record, but how to go on from there?

                Hannu
              • htrla57
                I think I found a solution to my problem, which was to pass context dependent data to a datatable formatter (I am handling a variable number of datatables with
                Message 7 of 7 , Jul 3, 2009
                • 0 Attachment
                  I think I found a solution to my problem, which was to pass context dependent data to a datatable formatter (I am handling a variable number of datatables with a single set of functions, and there is need for the formatter to be aware of the context).

                  The trick was to define the formatter separately for each datatable, like this:

                  tbl = new YAHOO.widget.DataTable(tblel, coldefs, ds) ;
                  var col = tbl.getColumn("deadline") ;
                  col.formatter = function(el, oR, oC, oD) { tdFormatter(el, oR, oD, ctx, tid) ; } ;
                  tbl.render() ;

                  Now the formatter function gets the correct values of ctx and tid in each datatable instance. In my original approach I had overlooked how closures work in Javascript, and ended up with incorrect values in the formatter.

                  There may still be a better way, though.
                Your message has been successfully submitted and would be delivered to recipients shortly.