locked
HTML table control: hiding and changing column names programmatically RRS feed

  • Question

  • Hi All

    There is probably a simple answer to this.

    Given a HTML table (new in VS2013) that has a column called 'Answer1', I assumed that I could use the .isVisible and .displayName to hide a column or change a column header like below....

    myapp.ViewTopic.Answer1_postRender = function (element, contentItem) {
        setTimeout(function () {
            contentItem.isVisible = false; 
            contentItem.displayName = "Testing123";
        }, 100); 
    };

    However this doesn't work. The .isVisible actually works when the table is in reflow mode (ie phone size), but not when it shows as a table.

    The .displayName doesn't seem to work at all.

    Is there a difference property that I should be accessing to table columns programmatically?

    Thank you, Matt




    Thursday, November 14, 2013 9:45 AM

All replies

  • Hi Matt

    Just a note on LS HTML tables and IE9, there is a bug that causes tables to not display in IE9 just in case your audience may be using that specific browser, the fix is scheduled for the next release, not sure when that is though.

    There is a workaround in this post:

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/4cd70bcc-69c1-458d-b1c9-d351e88c2738/lightswitch-html-table-data-not-displaying-in-internet-explorer-9?forum=lightswitch

    Thursday, November 14, 2013 1:12 PM
  • Thanks for the update...I hadn't come across that.

    However, this particular problem is occurring in Chrome (and I suspect all browsers). I'm actually not sure if it is a bug, or whether I should be accessing column headers in a completely different way?

    I wonder if anyone else might have some idea?

    Friday, November 15, 2013 12:27 AM
  • Hi,

    If you want to change DataGrid Column Headers or the label/display name of an editable grid, I'd like to suggest you to read the similar questions below for help:

    Programatically changing the label/display name of an editable grid

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/8a5cb410-82f4-472c-8c33-13afd52acb6c/programatically-changing-the-labeldisplay-name-of-an-editable-grid?forum=lightswitch

    Dynamically Changing DataGrid Column Headers

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/a6b15d00-41d0-4a51-9fe0-755ed36aa156/dynamically-changing-datagrid-column-headers?forum=lightswitch

    Hope it helps.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 15, 2013 12:59 PM
  • Hi Yunjie,

    Thanks for the reply, but both of the articles you referred me to are talking about the silverlight client.

    My question is referring to the new HTML Client table control, so I think the solution will be very different. Any ideas?

    Friday, November 15, 2013 6:45 PM
  • I am not sure about the right way, but this is how I have done this.

    myapp.BrowseGetFunctions.getBussinesUnitsByParameters_postRender = function (element, contentItem) {
        // Write code here.
        var thcolumns = $(element).find("th");
        thcolumns.each(function (index, item) {
            if (index == 1) {
                $(item).attr('colspan', 3);
                $(item).css("text-align", "center");
                $(item).text("Project Health");
            }
            else if (index > 1) {
                $(item).hide();
            }
        });
    };
    In this example I needed to make 3 columns under the same header and change column name.

    Friday, November 15, 2013 10:57 PM
  • OK, the above has been proposed as the answer by MSFT, and thanks nicksav for the suggestion. In order to hide the column, not only did I have to hide the <th> through DOM manipulation, but then had to hide the columns for each row that was rendered.

    It works, but it feels very clunky, especially since you would expect the isVisible and displayName properties to affect visibility and displayname for the columns in a grid ( otherwise what's the point of those properties).

    It just doesn't feel like the 'Lightswitch Way'.

    Still open to suggestions, but if there are not any, here is my code in case anyone else is interested.

    It either names or hides each column ( depending on data from another entity)

    myapp.ViewTopic.AnswersTable_postRender = function (element, contentItem) {
            var h1 = contentItem.screen.Topic.Heading1 || "";
            var hdr1 = $("th:Contains('Answer1')");
            if (h1)
                hdr1.text(h1)
            else
                hdr1.hide();
    
            var h2 = contentItem.screen.Topic.Heading2 || "";
            var hdr2 = $("th:Contains('Answer2')");
            if (h2)
                hdr2.text(h2)
            else
                hdr2.hide();
    
            var h3 = contentItem.screen.Topic.Heading3 || "";
            var hdr3 = $("th:Contains('Answer3')");
            if (h3)
                hdr3.text(h3)
            else
                hdr3.hide();
    
            var h4 = contentItem.screen.Topic.Heading4 || "";
            var hdr4 = $("th:Contains('Answer4')");
            if (h4)
                hdr4.text(h4)
            else
                hdr4.hide();
    
            var h5 = contentItem.screen.Topic.Heading5 || "";
            var hdr5 = $("th:Contains('Answer5')");
            if (h5)
                hdr5.text(h5)
            else
                hdr5.hide();
    };
    
    myapp.ViewTopic.Answer1_postRender = function (element, contentItem) {
        // Write code here.
        var h1 = contentItem.screen.Topic.Heading1 || "";
        if (!h1) contentItem.isVisible = false;
    };
    
    myapp.ViewTopic.Answer2_postRender = function (element, contentItem) {
        var h2 = contentItem.screen.Topic.Heading2 || "";
        if (!h2) contentItem.isVisible = false;
    };
    
    myapp.ViewTopic.Answer3_postRender = function (element, contentItem) {
        var h3 = contentItem.screen.Topic.Heading3 || "";
        if (!h3) contentItem.isVisible = false;
    };
    
    myapp.ViewTopic.Answer4_postRender = function (element, contentItem) {
        var h4 = contentItem.screen.Topic.Heading4 || "";
        if (!h4) contentItem.isVisible = false;
    };
    
    myapp.ViewTopic.Answer5_postRender = function (element, contentItem) {
        var h5 = contentItem.screen.Topic.Heading5 || "";
        if (!h5) contentItem.isVisible = false;
    };

     
    Thursday, November 21, 2013 12:07 PM
  • I agree, this seems like a ton of code to do something that (you would think) should be easy in a RAD tool.  After a number of really great apps with the SL client I am starting an HTML client project.  So far I really like certain aspects but the amount of JS that will be needed is very daunting. 
    Thursday, November 21, 2013 12:52 PM
  • Actually I'm finding that I'm having problems programmatically changing contentItem.displayName in several other places as well (not just the grid). It seems to have no effect? I end up resorting to DOM manipulation to change the display name (label) on controls. Is this right? What is the displayName property for then?
    Saturday, November 23, 2013 8:45 AM
  • I noticed that jQuery Mobile 1.3.0 has column toggle feature for table control. You could explore that as an option. It appears you'll still have to manipulate DOM to decorate hid able columns if you want users to toggle. http://view.jquerymobile.com/1.3.0/docs/widgets/table-column-toggle/ Hopefully LS will decorate th elements in future release to support this. Ps I think you need to use data binding to change properties like display name at runtime. Maybe that way LS client knows you've changed a property of the object and then updates DOM accordingly. HTH, Josh
    Thursday, November 28, 2013 6:27 PM
  • Hi,

    I'm trying to change the column name programatically but I have not been able to do it.

    Any ideas?

    Thanks,

    Dave

    Thursday, October 2, 2014 7:23 PM
  • Hi Dave,

    You can use dataBind to listen for a change on displayName property and then change the label text for the respective column.  The following code does this for a contentItem, but you could refactor the labelDiv selector to find the respective <th> text element.

    myapp.AddEditOrder.Zip_postRender = function (element, contentItem) {
        // on change of contentItem.displayName, set label text to newValue
        contentItem.dataBind("displayName", function (newValue) {
            if (!!newValue) {
                var labelDiv = $(element.parentNode).find("div.msls-label");
                labelDiv.find("label").text(newValue);
            }
        });
        //change displayName will fire dataBind callback
        contentItem.displayName = "ZIP CODE"

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/88b7196d-202c-421f-b182-54a7e87e0c7e/displayname-reverts-back-to-original-after-screen-refresh?forum=lightswitch

    Since a column contentItem postRender fires for every row, you'd prolly want to use the table _postRender, loop through the <th> elements to set the bindings only once per column.

    HTH,

    Josh

    Thursday, October 2, 2014 8:34 PM
  • Thanks Josh.

    This is my first HTML project so I know next to nothing about the DOM.  How would I access the <th> tags?  Is there some documentation on this?  All I want is to change the Header for a column.

    Thanks,

    Dave

    Thursday, October 2, 2014 9:21 PM
  • Here is what I get when I inspect the element.  The heading I want to change is in red border.  Thanks

    Thursday, October 2, 2014 11:28 PM
  • Hi Dave,

    This should do it (comments inline):

    myapp.BrowseOrders.Orders_postRender = function (element, contentItem) {
    
        //get array of columns from table contentItem
        var columns = contentItem.children[0].children;
    
        //get array of th elements inside table element as jQuery objects
        var thElements = $("th.msls-table-header", element);
    
        //for each column
        $(columns).each(function (index, colElement) {
            //find the msls contentItem object of the same name
            var colContentItem = contentItem.screen.findContentItem(colElement.name);
            //if found
            if (colContentItem) {
                //dataBind listen for change on contentItem.displayName prop
    	    colContentItem.dataBind("displayName", function (newValue) {
    	        if (!!newValue) {
                        //change the text of the th element to the newValue
    	            $(thElements[index]).text(newValue);
    	        }
    	    });
    	}
        });
        //call it by simply changing the displayName property from anywhere
       contentItem.screen.findContentItem("CustomerID").displayName = "CustID";
    };

    What this does is setup the binding between the displayName property of each column contentItem and the respective column header text.  Thus you can change the displayName anywhere in code and the header text will change (as it should be out of the box).

    PS...I haven't tested this on small screens so I'm not sure if the reflow would mess it up (?)

    HTH,

    Josh






    • Edited by joshbooker Friday, October 3, 2014 12:10 AM
    • Proposed as answer by Dave Vorgang Friday, October 3, 2014 5:32 PM
    Thursday, October 2, 2014 11:55 PM
  • Hi Josh,

    That works but it does mess up on small devices or when resizing the window and it reflows the screen.  

    Any idea on how to prevent that?

    Also, is it possible to disable the reflow and have a horizontal scroll bar kick in if the grid doesn't fit?

    Thanks

    Dave

    Friday, October 3, 2014 5:22 PM
  • Got it to work on small screens.  Put the:

      contentItem.screen.findContentItem("CustomerID").displayName = "CustID";

    on the Row Layout container.

    Thanks,

    Dave

    +1 you and proposed as answer.

    Friday, October 3, 2014 5:35 PM