[CLOSED] Align to width of longest label

  1. #1

    [CLOSED] Align to width of longest label

    Hi
    I have a dynamic form, where I read field labels from a data source and I want to align those labels by width of longest. Sample goes:
    X.FormPanel().BodyPadding(6).Items
        (
            items =>
            {
                string[] labels = new string[] { "this is some verrrrryyyyy looong label", "Normal label", "Short" };
                for (int i = 0; i < labels.Length; i++)
                {
                    items.Add
                    (
                        X.FieldContainer().Layout(LayoutType.HBox).LayoutConfig(new HBoxLayoutConfig() { Align = HBoxAlign.Middle }).Border(true)
                        .Items
                        (
                            fields =>
                            {
                                Label label = new Label(labels[i] + ":");
                                //label.Width = 110; //<== if I uncomment this I get behavior that I want but label is truncated
                                label.PaddingSpec = "0 6 0 0";
                                ComboBox comboOperators = new ComboBox();
                                comboOperators.Editable = false;
                                comboOperators.Width = 50;
                                comboOperators.FieldStyle = "text-align:center";
                                comboOperators.PaddingSpec = "0 6 0 0";
                                comboOperators.Items.AddRange(new ListItem[] { new ListItem("="), new ListItem("<>"), new ListItem(">"), new ListItem(">="), new ListItem("<"), new ListItem("<="), new ListItem("[]") });
                                comboOperators.SelectedItem.Index = 0;
                                TextField textField = new TextField();
                                textField.Width = 500;
                                textField.PaddingSpec = "0 6 0 0";
                                fields.AddRange(new ComponentBase[] { label, comboOperators, textField });
                            }
                        )
                    );
                }
            }
        )
    Last edited by fabricio.murta; Dec 28, 2015 at 12:07 PM. Reason: [CLOSED]
  2. #2
    Hello, @ingbabic!

    I am afraid there's no automatic way to do this. I've tried several layout combinations with no luck. So, I've wrote an event handler to attain that objective.

    To get it working, add the following script to your sample:
        <script>
            var equalizeFields = function (me, myAnchor) {
                var chosenWidth = -1;
                var myFormLines = me.items.items;
                var lineKeys = Object.keys(myFormLines);
    
                // Get max width between fields
                for (i = 0; i < lineKeys.length; i++) {
                    var lkey = lineKeys[i];
                    var formLine = myFormLines[lkey];
                    var fieldKeys = Object.keys(formLine.items.items);
                    var labelField = formLine.down("netlabel");
    
                    if (labelField != null) {
                        var curWidth = labelField.getWidth();
                        console.log("checking " + labelField.id + "(" + curWidth + "px)");
    
                        if (curWidth > chosenWidth) {
                            chosenWidth = curWidth;
                        }
                    }
                }
    
                // Do not allow width to exceed 500 pixels
                if (chosenWidth > 500) {
                    chosenWidth = 500;
                }
    
                // Apply it to any field shorter than it
                for (i = 0; i < lineKeys.length; i++) {
                    var lkey = lineKeys[i];
                    var formLine = myFormLines[lkey];
                    var fieldKeys = Object.keys(formLine.items.items);
                    var labelField = formLine.down("netlabel");
    
                    if (labelField != null) {
                        var curWidth = labelField.getWidth();
                        console.log("checking " + labelField.id + "(" + curWidth + "px)");
    
                        if (curWidth < chosenWidth) {
                            labelField.setWidth(chosenWidth);
                        }
                    }
                }
                console.log("assets[" + me + "," + myAnchor + "]::> "+chosenWidth);
            }
        </script>
    And the following Listener on your panel is enough to have it working:
    .Listeners(evnt => evnt.AfterLayout.Fn = "equalizeFields")
    Notice I added this listener to your FormPanel.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    It does exactly what I need, thanks :)

    Aside this question could you please explain me how do you manage to have comments like this (//) in JavaScript? When I copied your code in my project first I've got java script error: 0x800a03f1 - JavaScript runtime error: Expected '}'. I had to delete all comments and then it started to work.
  4. #4
    Glad it helped you!

    As for the JS comments, I do nothing special. They work in VS intellisense while looking on code, and on browser while running the code as well. It is an cshtml file and outside of @() razor blocks.

    It is also supposed to be supported by any JavaScript-compliant browser.
    Fabrício Murta
    Developer & Support Expert
  5. #5
    However it doesn't work by me. I have to use @**@ comment style. Comments like // doesn't work with exception I wrote. This happens in IE. Firefox and Chrome don't throw exception in Visual studio, but they don't show the page with Java script with // comments at all...
  6. #6
    That is because you are pasting the code inside a razor block. Although I also used a razor view, I used html code outside of razor blocks. As you just provided parts of the code I had to figure the rest out, and it happened not to be exactly the same shape you set up your pages.

    Look how does my example look like:

    
    @{
        Layout = null;
        var X = Html.X();
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>c60452_widthLongestLabel</title>
    
        <script>
            var equalizeFields = function (me, myAnchor) {
                var chosenWidth = -1;
                var myFormLines = me.items.items;
                var lineKeys = Object.keys(myFormLines);
    
                // Get max width between fields
                for (i = 0; i < lineKeys.length; i++) {
                    var lkey = lineKeys[i];
                    var formLine = myFormLines[lkey];
                    var fieldKeys = Object.keys(formLine.items.items);
                    var labelField = formLine.down("netlabel");
    
                    if (labelField != null) {
                        var curWidth = labelField.getWidth();
                        console.log("checking " + labelField.id + "(" + curWidth + "px)");
    
                        if (curWidth > chosenWidth) {
                            chosenWidth = curWidth;
                        }
                    }
                }
    
                // Do not allow width to exceed 500 pixels
                if (chosenWidth > 500) {
                    chosenWidth = 500;
                }
    
                // Apply it to any field shorter than it
                for (i = 0; i < lineKeys.length; i++) {
                    var lkey = lineKeys[i];
                    var formLine = myFormLines[lkey];
                    var fieldKeys = Object.keys(formLine.items.items);
                    var labelField = formLine.down("netlabel");
    
                    if (labelField != null) {
                        var curWidth = labelField.getWidth();
                        console.log("checking " + labelField.id + "(" + curWidth + "px)");
    
                        if (curWidth < chosenWidth) {
                            labelField.setWidth(chosenWidth);
                        }
                    }
                }
                console.log("assets[" + me + "," + myAnchor + "]::> "+chosenWidth);
            }
        </script>
    </head>
    <body>
        <div>
    @Html.X().ResourceManager()
    @(X.FormPanel()
        .BodyPadding(6)
        .Items(items =>
        {
            string[] labels = new string[] { "this is some verrrrryyyyy looong label", "Normal label", "Short" };
            for (int i = 0; i < labels.Length; i++)
            {
                items.Add(
                    X.FieldContainer().Layout(LayoutType.HBox).LayoutConfig(new HBoxLayoutConfig() { Align = HBoxAlign.Middle }).Border(true)
                    .Items(fields =>
                    {
                        Label label = new Label(labels[i] + ":");
                        //label.Width = 110; //<== if I uncomment this I get behavior that I want but label is truncated
                        label.PaddingSpec = "0 6 0 0";
                        ComboBox comboOperators = new ComboBox();
                        comboOperators.Editable = false;
                        comboOperators.Width = 50;
                        comboOperators.FieldStyle = "text-align:center";
                        comboOperators.PaddingSpec = "0 6 0 0";
                        comboOperators.Items.AddRange(new ListItem[] { new ListItem("="), new ListItem("<>"), new ListItem(">"), new ListItem(">="), new ListItem("<"), new ListItem("<="), new ListItem("[]") });
                        comboOperators.SelectedItem.Index = 0;
                        TextField textField = new TextField();
                        textField.Width = 500;
                        textField.PaddingSpec = "0 6 0 0";
                        fields.AddRange(new ComponentBase[] { label, comboOperators, textField });
                    })
                );
            }
        })
        .Listeners(evnt => evnt.AfterLayout.Fn = "equalizeFields")
    )
        </div>
    </body>
    </html>
    I believe this explains why I could use this comments on JavaScript code.
    Fabrício Murta
    Developer & Support Expert
  7. #7
    Hmm, my form is in partial view and I did put java script in that partial view. In that sense we can say that my partial view is inside razor block and thus I can't use // style comments, right?
  8. #8
    I'm sorry for being persistent on this, but I've noticed something. When I put this script in my project I have found out that it is terribly slow. It seems that reason for this is that each labelField.setWidth(chosenWidth); actually re-render panel so this method is being called as many times as there are labels inside. Maybe there is a possibility to set width without propagating events and to do it on last label only?
  9. #9
    There's nothing wrong with yor persistence, the suggestion had issues for your case and you couldn't figure a better way out, so let's try to help you, we're here for this!

    Try this event, here I got it calling only once in the same example after it loads. And you were right, the way it was here it called 3 times, I didn't really check that up and missed that detail.

    .Listeners(evnt => evnt.AfterRender.Fn = "equalizeFields")
    (just changed from AfterLayout to AfterRender)

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  10. #10
    Yes, now it's much faster. Thank you

Similar Threads

  1. [CLOSED] Bug in fieldcontainer when using label align top
    By Akpenob in forum 2.x Legacy Premium Help
    Replies: 3
    Last Post: Jun 24, 2014, 2:24 PM
  2. Replies: 1
    Last Post: Aug 21, 2013, 5:47 PM
  3. [CLOSED] [1.0] Combobox width auto set to longest item
    By betamax in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Aug 26, 2010, 9:30 PM
  4. Label Align
    By flaviodamaia in forum 1.x Help
    Replies: 1
    Last Post: Jul 29, 2009, 9:37 AM
  5. [CLOSED] Label Right Align
    By Etisbew in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Jun 16, 2009, 11:30 AM

Tags for this Thread

Posting Permissions