Create a Custom User Control that Uses the ID I give it and honors ClientIDMode="Static"

739 Views Asked by At

I have a few Custom Controls I built in C# for my Web App. Also I am using Visual Studio 2013.

Control:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="YearsTextBox.ascx.cs" Inherits="MutualExpert.Controls.YearsTextBox"  %>
<div class="input-group">
    <asp:TextBox ID="tb" runat="server" CssClass="form-control text-right" />
    <div class="input-group-addon">Years</div>
</div>

Calling it from the ASPX page I want to use it on:

<cc:YearsTextBox runat="server" ID="tbDamageLife" />

I want the Control to be rendered on the page as "tbDamageLife"

What I Tried:

If I specify ClientIDMode="Static" on then I get the ID="tb" :

<div class="input-group">
    <input name="ctl00$cpMain$tbDamageLife$tb" id="tb" class="form-control text-right" type="text">
    <div class="input-group-addon">Years</div>
</div>

If I don't then I get ID="ctl00_cpMain_tbDamageLife_tb" :

<div class="input-group">
    <input name="ctl00$cpMain$tbDamageLife$tb" id="ctl00_cpMain_tbDamageLife_tb" class="form-control text-right" type="text">
    <div class="input-group-addon">Years</div>
</div>

I just want it to render tbDamageLife, the ID I am giving it.

This is a tricky one, I need these to be static for JS to access it to do calculations. It is necessary. I would work around it if I could but I simply cannot.

3

There are 3 best solutions below

0
Mark Bad On BEST ANSWER

The team and I found an alternative way that end up being a lot less code on the HTML and JS sides of it and IMHO a lot easier to remember and work with for the team.

Simply speaking, add a CSS class name. Example:

<cc:YearsTextBox runat="server" ID="tbDamageLife" CssClass="tbDamageLife" />

In the user control:

    /// <summary>
    /// Gets or sets Class
    /// </summary>
    public string CssClass
    {
        get { return tb.CssClass; }
        set
        {
            // we need to make sure that form-control is always part of the Class
            if (value.Contains("form-control"))
                tb.CssClass = value;
            else
                tb.CssClass += " " + value;
        }
    }

and in JS:

    case _ui.newlevel.select:
        $(".tbDamageLife").removeAttr("disabled");
1
VDWWD On

A UserControl itself does not have an ID in html, only in code. So the best solution in your case would be to wrap the UserControl content inside a Panel and give that the ID tbDamageLife. That will become the <div> with the class input-group.

<asp:Panel ID="tbDamageLife" runat="server" CssClass="input-group">
    <asp:TextBox ID="tb" runat="server" CssClass="form-control text-right" />
    <div class="input-group-addon">Years</div>
</asp:Panel>

And on the parent page

<cc:YearsTextBox runat="server" ID="tbDamageLife" ClientIDMode="Static" />

Will render as

<div id="tbDamageLife" class="input-group">
    <input name="ctl00$cpMain$tbDamageLife$tb" type="text" id="tb" class="form-control text-right" />
    <div class="input-group-addon">Years</div>
</div>

However if you should add multiple controls you will have duplicate ID's.

Or you could simply do the following if you do not need the functionality of the Panel Control.

<div id="tbDamageLife" class="input-group">
    <asp:TextBox ID="tb" runat="server" CssClass="form-control text-right" />
    <div class="input-group-addon">Years</div>
</div>
1
dpant On

The user control acts as a "placeholder" and is replaced by its actual contents when the calling page is rendered:

<form method="post" id="form1">
    <div class="input-group">
        <input name="tbDamageLife$tb" type="text" id="tbDamageLife_tb" class="form-control text-right">
        <div class="input-group-addon">Years</div>
    </div>
</form>

In the above example, note that there is no element with tbDamageLife id. Rather, the user control id is used to produce unique identification for the contained TextBox (which is rendered). So, this is pretty standard behavior and a correct one, too.

Nevertheless, you can access the TextBox of the user control from javascript using ClientID, for example:

<form id="form1" runat="server">
    <div>
        <uc:YearsTextBox runat="server" ID="tbDamageLife" />
        <input type="button" value="OK" onclick="btnOK_Click()" />
    </div>
</form>
<script type="text/javascript">
    function btnOK_Click() {
        var ucTb = document.getElementById('<%= tbDamageLife.FindControl("tb").ClientID %>');

        console.log(ucTb.value);
    }
</script>

IMHO, this is the "safest" way to do it meaning that you are actually using the tbDamageLife id from the server code which does known about it.