views:

212

answers:

2

I have constructed several web services that successfully serialize my .NET types into JSON. However, I'm running into an issue getting the JSON to be fully compatible with the YUI library and the DataTable in particular.

The YUI DataTable can be fully configured using JSON objects. I created the following struct in .NET to represent a given YUI column definition:

 public struct YuiColumnDefinition{
        public string key;
        public string label;
        public bool sortable;
        public string formatter;
 }

The 'formatter' property is how you instruct the YUI table to use a custom javascript function when displaying a given column. The problem is that, since formatter is defined as a String, ASP.NET wraps it's value in double quotes upon serialization, and YUI no longer recognizes the value as a JavaScript token:

JSON YUI expects

[ 
{key:"1", label:"Order Date", formatter:myCustomJavaScriptFunction, sortable:true},
{key:"2", label:"Customer Name", formatter:null, sortable:false}
]

JSON ASP.NET creates

[ 
{key:"1", label:"Order Date", formatter:"myCustomJavaScriptFunction", sortable:true},
{key:"2", label:"Customer Name", formatter:null, sortable:false}
]

Anyone have a solution outside of modifying the YUI source code?

Thanks

+3  A: 

Change your parsing code.

Think of json as a replacement for xml, you wouldnt put a variable/function in xml. In either, you could easily identify the name or type (say from a list or enum) of the formatter to use. Then your parsing code would know that it should assign a variable/method as the "formatter" property.

Its just incorrect to return an actual variable/function in a callback like that. You could make it work but honestly its not the way to go.

I would do the following...

Change your return json to this.

[ 
{key:"1", label:"Order Date", formatterName:"myCustomJavaScriptFunction", sortable:true},
{key:"2", label:"Customer Name", formatterName:null, sortable:false}
]

Then in JS, lets assume that json is stored in variable returnedObj

function augmentReturnedObject(returnedObj)
{
    // validate that returnObj.formatterName (as a variable) is not undefined
    var isValidObj = (window[returnedObj.formatterName] !== undefined);

    if (isValidObj)
    {

        // this will return the actual function / variable, here we are assigning it to returnedObj.formatter
        returnedObj.formatter = window[returnedObj.formatterName];
    }
    else
    {
        returnedObj.formatter = null;
    }
}

You could easily reduce that down to this without much thought

function augmentReturnedObject(returnedObj)
{
    var specifiedMethod = window[returnedObj.formatterName];

    returnedObj.formatter = (specifiedMethod === undefined) ? null : window[returnedObj.formatterName];
}

So in the end you'd take your json object, and do augmentReturnedObject(returnedObj); and at that point you can pass returnedObj to YUI

Allen
Sorry, I edit the hell out of my posts.
Allen
+1 Great answer! I agonized over whether or not to mark your answer as the correct one, but in the end felt that the proper solution was to simply register the javascript using the hooks provided by the YUI DataTable API.
Dirk
A: 

As Allen correctly pointed out:

Its just incorrect to return an actual variable/function in a callback like that.

Still, I couldn't find anywhere in the YUI documentation that spells out how to deal with javascript functions returned as strings from either JSON or XML.

Thank goodness for blogs. As pointed out in this one, the "proper" way to register custom javascript formatting functions is by using YAHOO.widget.DataTable.Formatter:

JSON Column Definitions as returned from .ASMX

[              
 {key:"1", label:"Order Date", formatter:"myCustomJavaScriptFunction1", sortable:true},             
 {key:"2", label:"Customer Name", formatter:null, sortable:false}             
 {key:"3", label:"State", formatter:"myCustomJavaScriptFunction2", sortable:false}             
]

Javscript to wire up the YUI DataTable

YAHOO.widget.DataTable.Formatter.myCustomJavaScriptFunction1= this.myCustomJavaScriptFunction1;
YAHOO.widget.DataTable.Formatter.myCustomJavaScriptFunction2= this.myCustomJavaScriptFunction2;

function  myCustomJavaScriptFunction1(elCell, oRecord, oColumn, oData) {
   //do something
}

function  myCustomJavaScriptFunction2(elCell, oRecord, oColumn, oData){
   //do something
}
Dirk
This is fine, just as long as your realize its the exact same thing that I described.
Allen