How to remove span tag from WebControl when rendered

When using an ASP.NET CheckBox (and in out case, inherited from a CheckBox) it renders a span around the checkbox input control, this span control is affecting jQuery scripts.

Is it possible to remove this span when rendering?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Found this useful tip:

In Code Behind, use InputAttributes instead of Attributes.

For Example, type this:

chk.InputAttributes.Add("onchange", "updateFields()")

instead of this:

chk.Attributes.Add("onchange", "updateFields()")

or instead of inline declarations:

<asp:CheckBox ID="chk" runat="server" onchange="updateFields()" />

The last two will cause the wrapping span.

Method 2

I just tried this on a test page and I’m not getting the around my CheckBox controls… are you sure it’s the CheckBox that’s rendering this? Is it conditional?

UPDATE: OK, it appears to be conditional on whether or not the CheckBox has extra attributes, including a CssClass setting… or a “disabled” attribute.

Method 3

I don’t know if this will work on this particular example. But if you make your own WebControl and you never want it to render spans around itself you can override the Controls render method like this:

public class MyWebControl : WebControl
{

  /* Your code 
             between here */

  protected override void Render(HtmlTextWriter writer)
  {
    RenderContents (writer);
  }
}

I guess that you could add the same to an inherited CheckBox… something like this:

public class MyCheckBox : CheckBox 
{

  /* Your code 
             between here */

  protected override void Render(HtmlTextWriter writer)
  {
    RenderContents (writer);
  }
}

The basic problem with the solution is better explained here:
http://www.marten-online.com/net/stripping-span-tag-from-webcontrol.html

Method 4

I spent the last 3 hours pulling my hair to find a solution at this problem.

Here is what came out:

using System.Web.UI;
using System.Web.UI.WebControls;

/// <summary>
/// Represents a custom checkbox web control.
/// Prevents itself to be wrapped into a <span> tag when disabled.
/// </summary>
public class CustomCheckBox : CheckBox
{
    /// <summary>
    /// Renders the control to the specified HTML writer.
    /// </summary>
    /// <param name="writer">The HtmlTextWriter object that receives the control content.</param>
    protected override void Render(HtmlTextWriter writer)
    {
        // Use custom writer
        writer = new HtmlTextWriterNoSpan(writer);

        // Call base class
        base.Render(writer);
    }
}

Along with the custom control, you’ll need a custom HtmlTextWriter:

using System.IO;
using System.Web.UI;

/// <summary>
/// Represents a custom HtmlTextWriter that displays no span tag.
/// </summary>
public class HtmlTextWriterNoSpan : HtmlTextWriter
{
    /// <summary>
    /// Constructor.
    /// </summary>
    /// <param name="textWriter">Text writer.</param>
    public HtmlTextWriterNoSpan(TextWriter textWriter)
        : base(textWriter)
    { }

    /// <summary>
    /// Determines whether the specified markup element will be rendered to the requesting page.
    /// </summary>
    /// <param name="name">Name.</param>
    /// <param name="key">Tag key.</param>
    /// <returns>True if the markup element should be rendered, false otherwise.</returns>
    protected override bool OnTagRender(string name, HtmlTextWriterTag key)
    {
        // Do not render <span> tags
        if (key == HtmlTextWriterTag.Span)
            return false;

        // Otherwise, call the base class (always true)
        return base.OnTagRender(name, key);
    }
}

Just FYI, using:

checkbox.InputAttributes.Add("disabled", "disabled");

has the same effect but:

  1. It’s not as convenient as checkbox.Enalbed = false;
  2. The attribute is removed after a postback when the checkbox is in a ListView.

Method 5

    protected override HtmlTextWriterTag TagKey
    {
        get
        {              
            return HtmlTextWriterTag.Div;
        }
    }

should do

Method 6

Using Jquery

<script>
        $(".selector input").unwrap().addClass("cssclass");
</script>

Method 7

You can use the input/checkbox control directly if you don’t need a label, or can put one yourself:

<input type="checkbox" id="CheckBox1" runat="server" />
<label for="CheckBox1">My Label</label>

A CSS Adapter may be able to remove the span around the checkbox/label, but I haven’t seen one for that purpose.

Method 8

Why don’t you remove the span using .remove with jquery ?

Method 9

Can you use a literal control instead? There’s a big difference between these two alternatives:

<p>12345<asp:Label ID="lblMiddle" runat="server" Text="6"></asp:Label>7890</p>
<p>12345<asp:Literal ID="ltlMiddle" runat="server" Text="6"></asp:Literal>7890</p>

Method 10

I’ve found that by implementing a constructor like the one below, you can specify the container tag for your control.

public MyCustomControl() : base(HtmlTextWriterTag.Div)
{
}

You can replace the HtmlTextWriterTag with any of the aviable options, such as Div in the example above. The default is Span.

Method 11

$(document).ready(function() {
  /* remove the relative spam involving inputs disabled */
  $('input[type="checkbox"]').parent('.aspNetDisabled').each(function() {
    var $this = $(this);
    var cssClass = $this.attr('class');
    $this.children('input[type="checkbox"]').addClass(cssClass).unwrap().parent('label[for],span').first().addClass('css-input-disabled');
  });
});
/* CSS Example */
.css-input {
  position: relative;
  display: inline-block;
  margin: 2px 0;
  font-weight: 400;
  cursor: pointer;
}
.css-input input {
  position: absolute;
  opacity: 0;
}
.css-input input:focus + span {
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
}
.css-input input + span {
  position: relative;
  display: inline-block;
  margin-top: -2px;
  margin-right: 3px;
  vertical-align: middle;
}
.css-input input + span:after {
  position: absolute;
  content: "";
}
.css-input-disabled {
  opacity: .5;
  cursor: not-allowed;
}
.css-checkbox {
  margin: 7px 0;
}
.css-checkbox input + span {
  width: 20px;
  height: 20px;
  background-color: #fff;
  border: 1px solid #ddd;
  -webkit-transition: background-color 0.2s;
  transition: background-color 0.2s;
}
.css-checkbox input + span:after {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  font-family: "FontAwesome";
  font-size: 10px;
  color: #fff;
  line-height: 18px;
  content: "f00c";
  text-align: center;
}
.css-checkbox:hover input + span {
  border-color: #ccc;
}
.css-checkbox-primary input:checked + span {
  background-color: #5c90d2;
  border-color: #5c90d2;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="nofollow noreferrer noopener" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Generate from asp.net -->
<label for="CheckBox1" id="Label4" class="css-input css-checkbox css-checkbox-primary">
  <span class="aspNetDisabled">
    <input id="CheckBox1" 
           type="checkbox" 
           checked="checked" 
           disabled="disabled">
  </span>
  <span></span>Disabled
</label>

Method 12

Try adding a constructor to your class that looks like this:

public MyControl() : base() 
{
}

If you notice, controls will render as spans as default since that’s what the “WebControl” uses (if you use Reflector) :

protected WebControl() : this(HtmlTextWriterTag.Span) { }

Reference:
http://aspnetresources.com/blog/stripping_span_from_webcontrol

Method 13

i wonder, is there a reason no1 mentioned this:

public MyControl() : base(string.Empty)

i got this reading http://aspnetresources.com/blog/stripping_span_from_webcontrol that flaviotsf mentioned

Method 14

                <div class="onoffswitch">
                     <asp:CheckBox ID="example1" runat="server" AutoPostBack="true" OnCheckedChanged="chkWifiRequired_CheckedChanged" CssClass="aspNetDisabled onoffswitch-checkbox"/>
                    <label class="onoffswitch-label" for='<%= example1.ClientID.ToString() %>'>
                        <span class="onoffswitch-inner"></span>
                        <span class="onoffswitch-switch"></span>
                    </label>
                </div>
            /* remove the relative spam involving inputs disabled */
            $('input[name=""]').parent('.aspNetDisabled').each(function () {
                var $this = $(this);
                var cssClass = "onoffswitch-checkbox";
                $('input[name=""]').addClass(cssClass).unwrap().parent('label[for],span').first().addClass('onoffswitch-checkbox');
            });

This will allow you to use the check box normally, still have it call server side code, and use the toggle from bootstrap. (I’m using the Inspina theme but it should be the same format for other toggles)

Method 15

I just had this issue and used Jon’s answer, which is good and it works. The downside is that your class is defined within the codebehind and not your markup.

So I took the answer and made a progamatic way to retrieve all attributes for the control, copy them to InputAttributes and remove those copied attributes from attributes.

Note that while this extends from RadioButton, you could use the method to extend any control, such as labels or checkboxes.

using System.Web.UI;
using System.Web.UI.WebControls;

namespace Hidistro.UI.Common.Controls
{
    /// <summary>
    /// Just like a normal RadioButton, except that the wrapped span is disabled.
    /// </summary>
    public class CleanRadioButton : RadioButton
    {
        protected override void Render(HtmlTextWriter writer)
        {
            List<string> keysToRemove = new List<string>();

            foreach (object key in Attributes.Keys)
            {
                string keyString = (string)key;
                InputAttributes.Add(keyString, Attributes[keyString]);
                keysToRemove.Add(keyString);
            }

            foreach (string key in keysToRemove)
                Attributes.Remove(key);

            base.Render(writer);
        }
    }
}

This way, all you need to do is the following, and it will output tags without the span.

<namespace:CleanRadioButton class="class1" />
<namespace:CleanRadioButton class="class2" />

HTML output:
(note that “generated” is autogenerated)

<input id="generated" type="radio" name="generated" value="generated" class="class1">
<input id="generated" type="radio" name="generated" value="generated" class="class2">


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x