Get the Column Display names of a List

Jun 4, 2015 at 7:30 PM
Excellent plugin - thank you Marc. I do have one dilemma. I want to retrieve the display names of the columns - for my output. I don't want to hard code the display names - instead, I wish there was a way to grab them - using the internal names (preferably inside the GetListItems method).

I've seen this thread -> - but might not work because I only have the list name, not the view name. Plus I still have to do some sort of comparison between the internal names and the response - which is I think a bit too much.

Don't the default SP webservices do this by default?

Thanks Marc.
Jun 4, 2015 at 7:45 PM
Edited Jun 4, 2015 at 7:45 PM

The example you found is using CSOM, so it's a bit of apples and oranges.

If you'd like to grab the list schema, you can call GetList. Or, if you'd prefer to have SPServices do the work for you, call SPGetListItemsJson. The mapping will happen automagically, and you can override any individual mappings you'd like.

Jun 4, 2015 at 11:26 PM
I really like the SPGetListItemsJson function. But I fall into the "custom type" column problem.

See I'm trying to build a solution for our users where they can simply supply EITHER the column display names OR column internal names. But not both.

If they give me the display names, SPGetListItemsJson is perfect IF it can find even the custom types without manual mapping.

If they give me the internal names, I'm back to the original problem of getting the right display names for the columns.

GetList may have to do - but I will have to do the comparison manually.
Jun 4, 2015 at 11:34 PM
Actually, when I used SPGetListItemsJson and it wasn't bringing back a column, I just automatically assumed was a custom field type.

But its actually type "choice". Is this expected behavior?
Jun 5, 2015 at 11:37 AM
What you might want to do is give them a list of columns to choose from. You'll have the available columns if you call GetList.

SPGetListItemsJson should return Choice columns. I'll check into that.

Jun 5, 2015 at 11:38 AM
Also, there are other functions that can help here. Be sure to look at everything available, like SPGetDisplayFromStatic and SPGetStaticFromDisplay.

Jun 5, 2015 at 3:05 PM
Thank you Marc. You've been very helpful.

Let me look into those functions. Yes, I really would like to use SPGetListItemsJson - it's so much easier to work with.
Jun 5, 2015 at 10:00 PM
I just checked and in my test, a Choice column was returned correctly in the JSON provided by SPGetListItemsJson. If you see any more issues, post your code and we can try to work it out.

Jun 5, 2015 at 10:19 PM
I was able to use "GetList" to do what I need. The only thing is, I have to call your plugin 2x

Below is to initialize:
        colTypes : ['Text', 'Note', 'Choice', 'DateTime', 'User', 'TaxonomyFieldType'],
        listName : 'FAQ',
        columns : ['Question', 'Answer', 'Benefit Type']
The plugin is below:
(function($) {
    $.fn.parsonsListViewer = function(options) {
        var settings = $.extend({           
            listName : '',              
            columns : Array(),
            colTypes : Array('Text', 'Note', 'Choice'),
            showLatest : true, 
            data : false //you can pass json object as data
        }, options );

        var obj = {
            columns : Array(),
            fieldsToRead : '',
            query : '',             
            data : false,  //json object
            isJson : function (str) {
                    try {
                    } catch (e) {
                        return false;
                    return true;


        if( === false){
            //prelim checks
            if(typeof settings.listName == 'undefined' || settings.listName == ''){
                return false;
            if(typeof settings.columns == 'undefined' || settings.columns.length == 0){
                return false;
                return false;

        }else if(obj.isJson({             
            console.log(' is invalid');
            return false;


        function getListColumns(){
            var cols = Array();
            var ajax = $().SPServices({
                operation: "GetList",
                listName: settings.listName,
                async : false,
                completefunc: function(xData, Status) { 
                    if(Status == 'success'){
                        $(xData.responseXML).find("Fields > Field").each(function(x) {
                            var displayName = $(this).attr("DisplayName");
                            var internalName = $(this).attr("Name");        
                            var contentType = $(this).attr("Type");
                            // console.log($(this).context);
                            // console.log('displayName=>'+displayName+' internalName=>'+internalName+' contentType=>'+contentType);
                            if(($.inArray(displayName.trim(), settings.columns) != -1) 
                                && ($.inArray(contentType.trim(), settings.colTypes) != -1)){   
                                var col = {
                                    'displayName' : displayName,
                                    'internalName' : internalName,
                                    'contentType' : contentType
                obj.columns = cols;
        } //end getListColumns();

        function prepareQuery(){

            if(obj.columns.length == 0) {
                return false;

            var fieldsToRead = '';
                fieldsToRead += '<ViewFields>';
                for(var i=0; i < obj.columns.length; i++){
                    fieldsToRead += '<FieldRef Name="' + obj.columns[i].internalName + '" />'; 
               fieldsToRead +=  "</ViewFields>";
             var query = '';
                 query += '<Query>';
                 query +=   '<Where>';
                 query +=       '<Neq>';
                 query +=           '<FieldRef Name="ID"/><Value Type="Number">0</Value>';
                 query +=       '</Neq>';
                 query +=   '</Where>';
                    if(settings.showLatest == true){
                         query += '<OrderBy>';
                         query +=   '<FieldRef Name="Created" Ascending="FALSE"/>';
                         query += '</OrderBy>';
                 query += '</Query>';

                 obj.fieldsToRead = fieldsToRead; 
                 obj.query = query;

         function getListData(){
            var output = false;
            if(obj.columns.length == 0) {
                return output;
            var ajax = $().SPServices({
                operation: 'GetListItems',
                async: false,  
                listName: settings.listName,
                CAMLViewFields: obj.fieldsToRead,
                  CAMLQuery: obj.query,
                    completefunc: function (xData, Status) { 
                        if(Status == 'success'){
                            output = Array();
                            $(xData.responseXML).SPFilterNode("z:row").each(function(e) { 
                              // console.log($(this).context);    
                              var record = {};                        
                              for(var e=0; e<obj.columns.length; e++){                                  
                                    var attr = 'ows_' + obj.columns[e].internalName;
                                    record[obj.columns[e].displayName] = $(this).attr(attr);
                          //log error
                          return output;

       = JSON.stringify(output);

        } //end getData();    

        return this;

    };//end pluign
}( jQuery )); //end of IFFY
Jun 5, 2015 at 10:25 PM
I have to look at SPGetListItemsJson again and see what's going on.
Jun 8, 2015 at 7:48 PM
You're calling to different operations, one to get the list schema (GetList) and the other to get the list items (GetListItems). If you call GetListItemChangesSinceToken, you can get both in one call.

Jun 10, 2015 at 10:21 PM
GetListItemChangesSinceToken - thanks Marc.

I actually revised the code into 2 sections. I took your advise in the beginning.

So I have a UI - where users can select a list they want to display. Once they select a list - checkboxes appear - with the column names as the label. This is using your "GetList" method. The selected columns will create the CAML query string, and the Fields to read string - store it in hidden fields.

Then the second part is the output - using 'GetListItems'. It will use the stored XML strings from the previous steps.

I just need to figure out how to store these via server side, per webpart.

Do you have any ideas how to achieve this?
Jun 10, 2015 at 10:30 PM
It sounds like you're trying to rebuild the native list view management capabilities. Why not just use those?

Jun 10, 2015 at 10:42 PM
Edited Jun 10, 2015 at 10:44 PM
Because the native list view UI is horrible. Our company just had a major rebranding of our SP 2013. Its fully responsive, using Bootstrap, custom fonts, color scheme - the works. The UI elements of the entire site match and all have a certain look and feel to it.

But once you get to the lists - its SP all over again. I've tried to do the most I can w/ just CSS - but it can only do so much.

So that's when I discovered your plugin. I had used it in a couple of our lists - where I recreated the whole output. Complete with pagination, filter, sort, hide and collapse etc - and the most important thing - it matches our identity.

Users still maintain the list content via the backend. But the view is all new.

Now my boss wants to apply it to all lists. So this is where I'm at.
Jun 10, 2015 at 10:55 PM
I think you're working too hard for minimal use cases. Setting up list views is not a constant activity.

That said, it's doable, and you could probably sell it as a product (add-in).