ASP.NET: Scroll to control
Asked Answered
T

10

9

I've got a particularly large form in an page. When the form is validated and a field is invalid, I want to scroll the window to that control. Calling the control's Focus() doesn't seem to do this. I've found a JavaScript workaround to scroll the window to the control, but is there anything built into ASP.NET?

Tifanytiff answered 14/4, 2009 at 2:4 Comment(0)
L
8
Page.MaintainScrollPositionOnPostBack = False
Page.SetFocus(txtManagerName)
Luo answered 20/9, 2012 at 19:31 Comment(1)
And exactly where do you write Page.MaintainScrollPositionOnPostBack = False ?Ravens
T
5

SO I believe the problem is because I was trying to focus on HtmlGenericControls instead of WebControls.

I just ended up doing a workaround based off of:

http://ryanfarley.com/blog/archive/2004/12/21/1325.aspx http://www.codeproject.com/KB/aspnet/ViewControl.aspx

...in the interest of time.

public static void ScrollTo(this HtmlGenericControl control)
{
    control.Page.RegisterClientScriptBlock("ScrollTo", string.Format(@"

        <script type='text/javascript'> 

            $(document).ready(function() {{
                var element = document.getElementById('{0}');
                element.scrollIntoView();
                element.focus();
            }});

        </script>

    ", control.ClientID));
}

Usage:

if (!this.PropertyForm.Validate())
{
    this.PropertyForm.ErrorMessage.ScrollTo();
    failed = true;
}

(Although it appears Page.RegisterClientScriptBlock() is deprecated for Page.ClientScript.RegisterClientScriptBlock()).

Tifanytiff answered 14/4, 2009 at 23:59 Comment(0)
T
5

Are you using a Validation Summary on your page?

If so, ASP.NET renders some javascript to automatically scroll to the top of the page which may well override the automatic behaviour of the client side validation to focus the last invalid control.

Also, have you turned client side validation off?

If you take a look at the javascript generated by the client side validation you should see methods like this:

function ValidatorValidate(val, validationGroup, event) {
  val.isvalid = true;
  if ((typeof(val.enabled) == "undefined" || val.enabled != false) && 
      IsValidationGroupMatch(val, validationGroup)) {
    if (typeof(val.evaluationfunction) == "function") {
      val.isvalid = val.evaluationfunction(val);
      if (!val.isvalid && Page_InvalidControlToBeFocused == null &&
          typeof(val.focusOnError) == "string" && val.focusOnError == "t") {
        ValidatorSetFocus(val, event);
      }
    }
  }
  ValidatorUpdateDisplay(val);
}

Note the call to ValidatorSetFocus, which is a rather long method that attempts to set the focus to the control in question, or if you have multiple errors, to the last control that was validated, using (eventually) the following lines:

if (typeof(ctrl.focus) != "undefined" && ctrl.focus != null) {
  ctrl.focus();
  Page_InvalidControlToBeFocused = ctrl;
}

To get this behaviour to work, you would ideally need to ensure that all your validators are set to be client-side - server side validators will obviously require a postback, and that might affect things (i.e. lose focus/position) - and setting MaintainScrollPositionOnPostBack to true would probably cause the page to reload to the submit button, rather than the invalid form element.

Using the server side .Focus method will cause ASP.NET to render out some javascript "on the page load" (i.e. near the bottom of the page) but this could be being overriden by one of the other mechanisms dicussed above.

Transceiver answered 15/4, 2009 at 0:0 Comment(0)
C
2

Adding MaintainScrollPositionOnPostback is the closest that ASP.NET has built in, but won't necessarily jump to the invalid field(s).

<%@ Page MaintainScrollPositionOnPostback="true" %>
Clavicorn answered 14/4, 2009 at 2:8 Comment(2)
That is not what he's describing - he wants the page to jump to the part of the form which failed validation, not necessarily the position the user was at last time.Weese
It doesn't answer the question, but he did solve my problem. Thanks!Parley
G
2

Very simple solution is to set the SetFocusOnError property of the RequiredFieldValidator (or whichever validator control you are using) to true

Gomorrah answered 1/6, 2010 at 10:35 Comment(1)
weblogs.asp.net/dfindley/archive/2007/06/29/…Euxenite
W
1

Are you sure Focus() won't do what you're describing? Under the hood, it is essentially doing the "JavaScript workaround" - it writes some JS to the page which calls focus() on the control with the matching ID:

Whichever control had Focus() called last before the page finishes processing writes this to the page:

<script type="text/javascript">
//<![CDATA[
WebForm_AutoFocus('txtFocus2');//]]>
</script>
Weese answered 14/4, 2009 at 2:8 Comment(0)
S
1

Please insert these into your OnClick event

Page.MaintainScrollPositionOnPostBack = false;
Page.SetFocus("cliendID");
// or
Page.setFocus(control);
Staffer answered 20/1, 2023 at 9:38 Comment(0)
S
0

You should looks into jQuery and the ScrollTo plugin

http://demos.flesler.com/jquery/scrollTo/

Skied answered 14/4, 2009 at 2:7 Comment(0)
H
0

I've achieved something similar using basic HTML fragments. You just leave an element with a known ID:

<span id="CONTROL-ID"></span>

And then either via script, on on the server side change the url:

window.location += "#CONTROL-ID";

In the first case the page won't reload, it will just scroll down to the control.

Hathorn answered 14/4, 2009 at 23:39 Comment(0)
C
0

Paste the following Javascript:

function ScrollToFirstError() {
        Page_ClientValidate();
        if (Page_IsValid == false) {
            var topMostValidator;
            var lastOffsetTop;
            for (var i = 0; i < Page_Validators.length; i++) {
                var vld = Page_Validators[i];
                if (vld.isvalid == false) {
                    if (PageOffset(vld) < lastOffsetTop || lastOffsetTop == undefined) {
                        topMostValidator = vld;
                        lastOffsetTop = vld.offsetTop;
                    }
                }
            }
            topMostValidator.scrollIntoView();
        }
        return Page_IsValid;
    }

    function PageOffset(theElement) {
        var selectedPosY = 0;
        while (theElement != null) {
            selectedPosY += theElement.offsetTop;
            theElement = theElement.offsetParent;
        }
        return selectedPosY;
    }

Then call ScrollToFirstError() in your OnClientClick of the button that is saving, make sure the button has CausesValidation=true as well.

There you have it.

Caucasia answered 28/2, 2012 at 15:54 Comment(1)
Great suggestion. I improved it slightly to scroll the actual offending control into view by changing the line to: document.getElementById(topMostValidator.controltovalidate).scrollIntoView();Hippy

© 2022 - 2024 — McMap. All rights reserved.