1

I am trying to use the YUI datatable to display data from a JSON object which looks like this:

{"results":[{"label":"Column 1","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "},{"label":"Column 2","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit."},{"label":"Column 3","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "},{"label":"Column 4","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit."},{"label":"Column 5","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit."},{"label":"Column 6","notes":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "}]}

I can do this fine with the standard implementation. However, the column names (labels in above object) are dynamic so I will not know them until the data reaches the page. I therefore want to define the column definitions from the datasource which I am doing in doBeforeParseData().

From reading / IRC, it has been suggested that I should be able to add columns to the data table. I want the table to look like this:

Column 1 Column 2.......

note note.....

so the above data should produce one row of data. Here's what I have so far:

function loadTable() {

  YAHOO.example.Basic = function() {


    var myColumnDefs = [];

    var myDataSource = new YAHOO.util.DataSource("/index/testajax");
    myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;


    myDataSource.doBeforeParseData = function (oRequest, oFullResponse, oCallback) {

       // alert(oFullResponse);

        var colDefs = [];
        var len = oFullResponse.results.length;
        for (var i = 0; i < len; i++) {
            var obj = {
                key: oFullResponse.results[i].label,
                sortable: true,
                resizeable: true
            };
            myColumnDefs.push(obj);

        }
            console.log(myColumnDefs);  
        return oFullResponse;
    };

    myDataSource.responseSchema = {
        resultsList:"results",
        fields: ["label","notes"]
    };

    var myDataTable = new YAHOO.widget.DataTable("json",
            myColumnDefs, myDataSource, {caption:"DataTable Caption"});

    return {
        oDS: myDataSource,
        oDT: myDataTable
    };
}();


}

Would be grateful for on any input on HOW to do this rather than why I shouldn't ;-)

thanks,

codecowboy

codecowboy
  • 9,835
  • 18
  • 79
  • 134

1 Answers1

4

I spent a bit of my lunch hour on this, but I got something working for you. I looked at your JSON and the way you did it would not work in the data table. results is a list, every entry is a row, and every attribute is a column. Here is the json that I came up with that I hope works for you.

{
    "resultSet":{
        "columnList":[
            {"key":"Column1","label":"My Col 1"},
            {"key":"Column2","label":"My Col 2"},
            {"key":"Column3","label":"My Col 3"}
        ],
        "results":[
            {
                "Column1":"Row 1 value",
                "Column2":"Row 1 value",
                "Column3":"Row 1 value"
            },
            {
                "Column1":"Row 2 value",
                "Column2":"Row 2 value",
                "Column3":"Row 2 value"
            }
        ]
    }
}

I made a small javascript object for handling what you need to do. What needs to be done is you need to make an ajax call to the server for the data. This is so you can define the columns in the datasource before you MAKE the datasource.

function DataProvider(url){
            this.url = url;
        }

        DataProvider.prototype = {
            url:null,
            data:null,
            ds:null,
            getData:function() {return this.data},
            initialize:function(){
                YAHOO.util.Connect.asyncRequest('GET', this.url, this);
            },
            success:function(response){
                var responseVal = YAHOO.lang.JSON.parse(response.responseText);
                var columnList = responseVal.resultSet.columnList;
                this.data = responseVal.resultSet.results;
                this.ds = new YAHOO.util.FunctionDataSource(function(){return this.dataProvider.getData()});
                this.ds.responseSchema = {
                    resultsList:"resultSet.results",
                    fields:columnList
                }
                this.ds.dataProvider = this;
                /* make call to initialize your table using the data set */
                var myDataTable = new YAHOO.widget.DataTable("basic", columnList, this.ds, {caption:"DataTable Caption"});

                //console.debug(columnList);
                //console.debug(this.data);
            }
        }

So when the page loads do the following

function init(){
    var dataProvider = new DataProvider('testjson.json');
    dataProvider.initialize();
}

And your html should look like this

<body onload="init()" class="yui-skin-sam">
    <div id="basic"></div>
</body>

And you should have the following scripts included

<!-- css -->
    <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/datatable/assets/skins/sam/datatable.css">
    <!-- js -->
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/connection/connection-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/datasource/datasource-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/element/element-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/datatable/datatable-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/json/json-min.js"></script> 

That should work, works for me in both IE and firefox.

Zoidberg
  • 10,137
  • 2
  • 31
  • 53
  • Thanks for the reply. To be clear, would the data coming back from my JSON call contain these meta fields? – codecowboy Aug 18 '09 at 15:58
  • Yes, in the answer, the return json is what comes back from the server. This will allow you to define your columns in the meta data that comes back in the json request from the server. – Zoidberg Aug 18 '09 at 16:16
  • I get oFullResponse.response is undefined – codecowboy Aug 18 '09 at 16:50
  • What JSON is coming into your data table? If you need to use Firebug to check it (if you don't already have it). Also try oFullResponse.meta.ColumnList and see if that is defined. I haven't used the meta data in the function you are using. You can also do this after the data is fully loaded and the table is rendered if you'd like. – Zoidberg Aug 18 '09 at 18:42
  • I have tried multiple variations. Also, is your 'columnList' supposed to equate to my columnDefs? JSONLint complains at "columnList":[{label:'my column',key:'column1'}] As the label and key need to be in quotes. Which begs the question - is this going to work? – codecowboy Aug 20 '09 at 15:45
  • Yeah column list must be in quotes for the JSON parser to parse it properly. The data in column list can be whatever you want it to be, your going to be using it directly to add your columns on the fly. The meta data part of the response schema specifies fields that are in the JSON as pure meta data. This is a list of variable names it will look for in your json. It will then put the data retreived from the fields under the same name in the meta property of the response object. Would you like me to do a complete example and post it? The one I posted was just a quick one. – Zoidberg Aug 20 '09 at 16:02
  • 1
    if you have the time, that would be legendary! It is driving me mental :-( The important bit for me is that the column names are not known until the JSON data comes back and I need to understand how to add my 'notes' as fields under the columns. thanks! – codecowboy Aug 20 '09 at 16:08
  • 1
    Ahh, i get it now... you don't know the columns at all, so you can't define them in your dataset. Let me think about this and I will update my answer. – Zoidberg Aug 20 '09 at 16:25
  • Thanks loads for taking the time to do this. It looks great. I will let you know when I've had a chance to try it. – codecowboy Aug 20 '09 at 19:45