locked
Can only center last label in Row Layout RRS feed

  • Question

  • I'm just starting out with the HTML client and, clearly, I'm doing something wrong. But I'm not even sure what a lot of things are called so I don't know what to search for to help myself. But I'm thinking that the problem lies in my lack of understanding of jQuery as this should be really simple.

    I have the following layout:

    Screen Designer

    With the following code behind:

    myapp.Splash.lblCopyright_postRender = function (element, contentItem) {
        $("label").addClass("custom-center-label");
    };

    And the following in user-customization.css:

    /* Custom Classes */
    .custom-center-label {
        text-align: center;
    }

    My screen ends up looking like this:

    Resultant page

    I can see in the DOM Explorer that the class is getting applied correctly and the Computed properties call for text-align to be center.

    DOM Explorer

    So I have two questions. First and foremost, why can I only get the last label in my Row Layout to be centered when all labels have the same class? And second, why, with the code that I have in the single Local Property's function, do all label's get the class added?



    • Edited by kyle ls Wednesday, September 23, 2015 10:46 PM
    Wednesday, September 23, 2015 10:39 PM

Answers

  • $("label") is a jQuery selector that returns all <label> elements in the document.

    That's why $("label").addClass will add the class to every label in the document.

    In LS _postrender if you want to affect only the respective contentItem you would work on the 'element' variable like Michael suggested.  The element variable represents the contentItemPresenter element which wraps every contentItem in the DOM (it's the div with class msls-presenter).

    To set the class to all labels in the element you could do this:

    $(element).find("label").addClass

    The trouble you're having probably has to do with the size of the containers around the labels.  If they are not the same width for example then the text won't look centered - even though it is centered in it's own container. 

    I find LS labels have a mind of their own.  Perhaps try changing the layout control from Label to Paragraph.  This renders much simpler HTML so it's better for static text than relying on the label of an empty contentItem.

    Then in the screen designer, set labels on each to  'none', and set the contentItem.value in postrender method.  

    Also add !important to your custom style.

    Like this - not tested:

    myapp.Splash.lblCopyright_postRender = function (element, contentItem) {
        $(element).find("p").addClass("custom-center-label");
        contentItem.value = "My Copyright Text Here";
    
    };
    
    /* Custom Classes */
    .custom-center-label {
        text-align: center !important;
    }

    Even with the above it will be important that all the size and alignment settings are the same in the screen designer (fit to content, stretch, min max width etc.) in order to get them to all center the same.

    HTH,

    Josh

     

     


    • Edited by joshbooker Thursday, September 24, 2015 12:21 AM
    • Marked as answer by kyle ls Thursday, September 24, 2015 3:41 PM
    Thursday, September 24, 2015 12:17 AM
  • setTimeout(function(){
        $(element).find("label").addClass("myClass");
    },500)

    This did not work. I think you're right that labels are just wonky and shouldn't be used.

    contentItem.screen.lblCopyright = "My Copy Text";

    This worked but required the timeout as above. This resulted in a slight delay after the screen rendered before this control was populated.

    $(element).find("p").text("My Copy Text");

    This worked without modification and so appears immediately. This seems to be the way to go. Thanks!

    • Marked as answer by kyle ls Thursday, September 24, 2015 3:41 PM
    Thursday, September 24, 2015 3:41 PM

All replies

  • I see you added the class the:

    lblCopyright_postRender

    Did you do the same for the other two labels?


    Unleash the Power - Get the LightSwitch HTML Client / SharePoint book

    http://LightSwitchHelpWebsite.com

    Wednesday, September 23, 2015 10:46 PM
  • I've added them and not added them. The result is the same. Even with only one function, all labels get the class custom-center-label added to the label tag. With all three functions, the same code just gets executed three times.

    And the Copyright is the top most label and it is not getting centered.

    • Edited by kyle ls Wednesday, September 23, 2015 10:50 PM
    Wednesday, September 23, 2015 10:49 PM
  • Try:

    myapp.Splash.lblCopyright_postRender = function (element, contentItem) {
        $(element).addClass("custom-center-label");
    };


    Unleash the Power - Get the LightSwitch HTML Client / SharePoint book

    http://LightSwitchHelpWebsite.com

    Wednesday, September 23, 2015 11:10 PM
  • If that doesn't work. One more thing to try is to see if the other labels will center if you put enough text in them to cause it to wrap.

    Unleash the Power - Get the LightSwitch HTML Client / SharePoint book

    http://LightSwitchHelpWebsite.com

    Wednesday, September 23, 2015 11:16 PM
  • $("label") is a jQuery selector that returns all <label> elements in the document.

    That's why $("label").addClass will add the class to every label in the document.

    In LS _postrender if you want to affect only the respective contentItem you would work on the 'element' variable like Michael suggested.  The element variable represents the contentItemPresenter element which wraps every contentItem in the DOM (it's the div with class msls-presenter).

    To set the class to all labels in the element you could do this:

    $(element).find("label").addClass

    The trouble you're having probably has to do with the size of the containers around the labels.  If they are not the same width for example then the text won't look centered - even though it is centered in it's own container. 

    I find LS labels have a mind of their own.  Perhaps try changing the layout control from Label to Paragraph.  This renders much simpler HTML so it's better for static text than relying on the label of an empty contentItem.

    Then in the screen designer, set labels on each to  'none', and set the contentItem.value in postrender method.  

    Also add !important to your custom style.

    Like this - not tested:

    myapp.Splash.lblCopyright_postRender = function (element, contentItem) {
        $(element).find("p").addClass("custom-center-label");
        contentItem.value = "My Copyright Text Here";
    
    };
    
    /* Custom Classes */
    .custom-center-label {
        text-align: center !important;
    }

    Even with the above it will be important that all the size and alignment settings are the same in the screen designer (fit to content, stretch, min max width etc.) in order to get them to all center the same.

    HTH,

    Josh

     

     


    • Edited by joshbooker Thursday, September 24, 2015 12:21 AM
    • Marked as answer by kyle ls Thursday, September 24, 2015 3:41 PM
    Thursday, September 24, 2015 12:17 AM
  • Excellent explanation and thanks for the detailed vocabulary descriptions. They were very helpful.

    You are indeed right that the problem was in the size of the containers. I cross posted on StackOverflow and @Kris suggested changing the Width property to Stretch to Container. That worked well and gave me the desired look.

    $(element).find("label").addClass however, did not work and the class was not applied to the label.

    I like the idea of using paragraphs and does generate simpler HTML that I am more familiar with. That did not work either but failed in a different way. The class was applied to the paragraph tag (which makes me question why find("label") didn't work properly) but contentItem.value did not properly populate the tag.

    Paragraph not working

    Any ideas on where I'm going wrong with this approach?

    Thursday, September 24, 2015 3:05 PM
  • Excellent explanation and thanks for the detailed vocabulary descriptions. They were very helpful.

    You are indeed right that the problem was in the size of the containers. I cross posted on StackOverflow and @Kris suggested changing the Width property to Stretch to Container. That worked well and gave me the desired look.

    $(element).find("label").addClass however, did not work and the class was not applied to the label.

    Perhaps the label was not rendered when this code executed.  You can wrap in setTimeout to fix this like so:

    setTimeout(function(){
        $(element).find("label").addClass("myClass");
    },500)
    <

    I like the idea of using paragraphs and does generate simpler HTML that I am more familiar with. That did not work either but failed in a different way. The class was applied to the paragraph tag (which makes me question why find("label") didn't work properly) but contentItem.value did not properly populate the tag.

    Guess I was wrong about contentItem.value updating the ui.

    Try setting screen property:

    contentItem.screen.lblCopyright = "My Copy Text";

    or <p> text directly:

    $(element).find("p").text("My Copy Text");

    HTH,

    Josh

    Thursday, September 24, 2015 3:27 PM
  • setTimeout(function(){
        $(element).find("label").addClass("myClass");
    },500)

    This did not work. I think you're right that labels are just wonky and shouldn't be used.

    contentItem.screen.lblCopyright = "My Copy Text";

    This worked but required the timeout as above. This resulted in a slight delay after the screen rendered before this control was populated.

    $(element).find("p").text("My Copy Text");

    This worked without modification and so appears immediately. This seems to be the way to go. Thanks!

    • Marked as answer by kyle ls Thursday, September 24, 2015 3:41 PM
    Thursday, September 24, 2015 3:41 PM
  • Glad it's working.  Since you're doing static text you've found a way that works but...
    contentItem.screen.lblCopyright = "My Copy Text";

    This worked but required the timeout as above. This resulted in a slight delay after the screen rendered before this control was populated.

     I'm surprised a timeout is required for the above as changing the property should update the UI via binding.

      If you were needing the text to be dynamic, you could try this same code in the screen_created method or of course reduce the timeout to 100 milliseconds - sometimes even 1 ms is enough to correct the timing and is not noticeable.

    Josh

    Thursday, September 24, 2015 4:04 PM
  • In the Silverlight version of my project, most of dynamic properties are populated in the screen's created method so I'll probably stick with that. I've read a lot about how certain things need timeouts in the HTML client. I'd like to stay away from them as much as possible as speed is the number one complaint about the Silverlight version and I'd rather not adjust a timeout to be low enough to not be noticable and t hen have it not work on some client with a slow machine or slow connection. But thanks for the alternative ideas.
    Thursday, September 24, 2015 5:24 PM
  • One last question. If I do:

    myapp.Splash.created = function (screen) {
        screen.lblCopyright = "©2012-2016, MyCompany, Inc."
    
    };

    Is there a way to add a class to the property in the created method as well or does that need to be done in postRender?

    Thursday, September 24, 2015 5:57 PM
  • LS has a method to find a contentItem from the screen object, but no method to get the contentItem's respective presenter DOM element (element var in postrender).

    I would use

    contentItem._view._container[0]

    to get the DOM 'element' from a contentItem.

     
    myapp.Splash.created = function (screen) {
        var contentItem = screen.findContentItem("lblCopyright");
        var element = contentItem._view._container[0];
        $(element).find("p").addClass("custom-center-label");
        screen.lblCopyright = "©2012-2016, MyCompany, Inc."
    };

    But some folks frown on using the so called 'internal' properties signified by the underscore.

    If you want to get bogged down in that debate then have a read of this:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/e46bc850-80bd-494b-b0b9-e37fa58f1ef7/html-client-how-to-get-the-contentvalue-of-a-custom-control?forum=lightswitch

    PS.. If you're weary of the underscore then for purpose of your splash screen you couls just add the class to all <P>s like so:

    $("p").addClass("custom-center-label");

    HTH,

    Josh




    • Edited by joshbooker Thursday, September 24, 2015 6:27 PM PS
    Thursday, September 24, 2015 6:16 PM
  • One more thing I forgot to mention:

    jQuery selectors can accept an optional second parameter representing the context.

    http://api.jquery.com/jQuery/#jQuery-selector-context

    so this:

     $(element).find("p").addClass("custom-center-label");

    is the same as this:

     $("p", element).addClass("custom-center-label");

    Thursday, September 24, 2015 7:59 PM