2

I am trying to have server + client-side validation for my registration page. I want to invoke a JS func when my TextBox control loses focus(onBlur).

Code in aspx page

<div id="nameDiv">              
    <asp:UpdatePanel ID="updatePanelName" runat="server">
        <ContentTemplate>
            <asp:Label ID="labelName" runat="server" Text="Enter Your Name"></asp:Label>
            <asp:TextBox ID="textBoxName" runat="server" placeholder="Enter Your Name" 
              onBlur="check(this)"></asp:TextBox>
            <i class="fa fa-exclamation-circle errorSign" id="errorIcon" runat="server"></i>                      
            <asp:Label ID="labelNameError" runat="server" Text="Name can't be blank" ForeColor="Red"> 
              </asp:Label>
        </ContentTemplate>
    </asp:UpdatePanel>
</div>

Javascript Code

function check(txtBox) {
    var errIcon = document.getElementById("<%= errorIcon.ClientID %>");
    txt = txtBox.value;
    if (txt.length < 1)
        errIcon.style.visibility = "visible";
}

CSS

input[type=text] {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display:inline-block;
    position:relative;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
}


.errorSign{
    position:absolute;
    margin-right:30px;
    left:1050px;
    top:220px;
    visibility:hidden;
}
  • @PatrickEvans do you know how .NET works? – epascarello Nov 20 '19 at 13:26
  • 1
    Why are you using runat="server" on an element? just drop it and use the regular id. – epascarello Nov 20 '19 at 13:27
  • You are not actually using it. How about `this.closest("#nameDiv").querySelector(".errorSign")` – mplungjan Nov 20 '19 at 13:28
  • `` Let asp.net set the id than you can use ClientId – Eldar Nov 20 '19 at 13:30
  • @Eldar um, how is that any different than OP has? – epascarello Nov 20 '19 at 13:31
  • Are you sure `check(this)` works? I have not worked .NET and JS together but `this` works differently in JS – alireza Nov 20 '19 at 13:31
  • `this` would be the textbox, that is how JavaScript works @alireza – epascarello Nov 20 '19 at 13:32
  • @epascarello **"ID"** is server side id. – Eldar Nov 20 '19 at 13:32
  • 2
    be easier to do it without ids. `var errIcon = txtBox.nextElementSibling` – epascarello Nov 20 '19 at 13:33
  • Where is your javascript hosted? Is it in an external `.js` file? If so, it's never going to work – freefaller Nov 20 '19 at 13:35
  • Little mistake corrected, instead of txt.style.visibility = "visible"; it is errIcon.style.visibility="visible" Still same problem – Abhishek Bajpai Nov 20 '19 at 13:37
  • @Eldar I think youre missing the point here, epascarello is correct, you dont even need the id to achieve the functionality needed. You also dont need the 'i' element rendered on the server. – Vince Nov 20 '19 at 13:38
  • @Vince guys I tried without runat="server" but still, it can't find the element and gives null. And this keyword thing works absolutely well and I even tried to find the textBox Element using every possible method but again the same problem persists. – Abhishek Bajpai Nov 20 '19 at 13:42
  • document.getElementById("errorIcon"); – Vince Nov 20 '19 at 13:43
  • @freefaller yes its an external js file, can you please elaborate the functionality of why is it not working? – Abhishek Bajpai Nov 20 '19 at 13:44
  • I was trying to tell how server side rendering works. Wasn't focusing anything else. By the way its not next sibling its previous sibling. you can use also `var errorIcon = txtBox.closest('.errorSign')` – Eldar Nov 20 '19 at 13:45
  • 2
    Because external .js files are not processed via ASP.Net (IIS will just send the file without any changes). In order for the code to work the `<%=...%>` must be within the `.aspx/.ascx` file – freefaller Nov 20 '19 at 13:47
  • `<%= errorIcon.ClientID %>` is a server-side expression. You would need to render the javascript on the server before sending it to the browser for that to work. If that is literally the javascript you see in the browser dev tools or page source then it won't work because that is not javascript, it is just a string at that point. – Crowcoder Nov 20 '19 at 13:47
  • @epascarello thanks man, nextElementSibling worked for me. But still, it tingles me why is it not able to find that element by id, maybe I am missing something in the functionality or life cycle of aspx web page of how it renders the elements. – Abhishek Bajpai Nov 20 '19 at 13:53

1 Answers1

2

The OP has stated via a comment that...

yes its an external js file

The reason why it's failing is that .js files are not processed by ASP.Net and will be sent to the browser without any changes. That means the browser is receiving the line exactly as it's written...

var errIcon = document.getElementById("<%= errorIcon.ClientID %>");

There are multiple ways to fix this... the first is probably not ideal, but it is to put the script into your .aspx or .ascx file.

That would mean that the script (being part of an ASP.Net processed page) will have the actual id of the control, instead of the <%=..%>.


The second, and probably better, way is to use the class name directly, rather than the id...

var errIcon = document.getElementsByClassName("errorSign")[0];

As getElementsByClassName returns an array of elements (because it's possible for multiple elements on the page to have the same class) the above will return the first item in that array. If your code is more complicated, you'll need to amend it accordingly


Another option (thanks to @epascarello) is to use nextElementSibling, but that is likely to break if you change the HTML for some reason (say a redesign of the page)...

var errIcon = txtBox.nextElementSibling;
freefaller
  • 19,368
  • 7
  • 57
  • 87