28
votes

Dynamically creating a radio button using eg

var radioInput = document.createElement('input');
radioInput.setAttribute('type', 'radio');
radioInput.setAttribute('name', name);

works in Firefox but not in IE. Why not?

11

11 Answers

26
votes

Taking a step from what Patrick suggests, using a temporary node we can get rid of the try/catch:

function createRadioElement(name, checked) {
    var radioHtml = '<input type="radio" name="' + name + '"';
    if ( checked ) {
        radioHtml += ' checked="checked"';
    }
    radioHtml += '/>';

    var radioFragment = document.createElement('div');
    radioFragment.innerHTML = radioHtml;

    return radioFragment.firstChild;
}
9
votes

Based on this post and its comments: http://cf-bill.blogspot.com/2006/03/another-ie-gotcha-dynamiclly-created.html

the following works. Apparently the problem is that you can't dynamically set the name property in IE. I also found that you can't dynamically set the checked attribute either.

function createRadioElement( name, checked ) {
    var radioInput;
    try {
        var radioHtml = '<input type="radio" name="' + name + '"';
        if ( checked ) {
            radioHtml += ' checked="checked"';
        }
        radioHtml += '/>';
        radioInput = document.createElement(radioHtml);
    } catch( err ) {
        radioInput = document.createElement('input');
        radioInput.setAttribute('type', 'radio');
        radioInput.setAttribute('name', name);
        if ( checked ) {
            radioInput.setAttribute('checked', 'checked');
        }
    }

    return radioInput;
}
4
votes

Here's an example of more general solution which detects IE up front and handles other attributes IE also has problems with, extracted from DOMBuilder:

var createElement = (function()
{
    // Detect IE using conditional compilation
    if (/*@cc_on @*//*@if (@_win32)!/*@end @*/false)
    {
        // Translations for attribute names which IE would otherwise choke on
        var attrTranslations =
        {
            "class": "className",
            "for": "htmlFor"
        };

        var setAttribute = function(element, attr, value)
        {
            if (attrTranslations.hasOwnProperty(attr))
            {
                element[attrTranslations[attr]] = value;
            }
            else if (attr == "style")
            {
                element.style.cssText = value;
            }
            else
            {
                element.setAttribute(attr, value);
            }
        };

        return function(tagName, attributes)
        {
            attributes = attributes || {};

            // See http://channel9.msdn.com/Wiki/InternetExplorerProgrammingBugs
            if (attributes.hasOwnProperty("name") ||
                attributes.hasOwnProperty("checked") ||
                attributes.hasOwnProperty("multiple"))
            {
                var tagParts = ["<" + tagName];
                if (attributes.hasOwnProperty("name"))
                {
                    tagParts[tagParts.length] =
                        ' name="' + attributes.name + '"';
                    delete attributes.name;
                }
                if (attributes.hasOwnProperty("checked") &&
                    "" + attributes.checked == "true")
                {
                    tagParts[tagParts.length] = " checked";
                    delete attributes.checked;
                }
                if (attributes.hasOwnProperty("multiple") &&
                    "" + attributes.multiple == "true")
                {
                    tagParts[tagParts.length] = " multiple";
                    delete attributes.multiple;
                }
                tagParts[tagParts.length] = ">";

                var element =
                    document.createElement(tagParts.join(""));
            }
            else
            {
                var element = document.createElement(tagName);
            }

            for (var attr in attributes)
            {
                if (attributes.hasOwnProperty(attr))
                {
                    setAttribute(element, attr, attributes[attr]);
                }
            }

            return element;
        };
    }
    // All other browsers
    else
    {
        return function(tagName, attributes)
        {
            attributes = attributes || {};
            var element = document.createElement(tagName);
            for (var attr in attributes)
            {
                if (attributes.hasOwnProperty(attr))
                {
                    element.setAttribute(attr, attributes[attr]);
                }
            }
            return element;
        };
    }
})();

// Usage
var rb = createElement("input", {type: "radio", checked: true});

The full DOMBuilder version also handles event listener registration and specification of child nodes.

4
votes

Personally I wouldn't create nodes myself. As you've noticed there are just too many browser specific problems. Normally I use Builder.node from script.aculo.us. Using this your code would become something like this:

Builder.node('input', {type: 'radio', name: name})
3
votes

My solution:

html
    head
        script(type='text/javascript')
            function createRadioButton()
            {
               var newRadioButton
                 = document.createElement(input(type='radio',name='radio',value='1st'));
               document.body.insertBefore(newRadioButton);
            }
    body
        input(type='button',onclick='createRadioButton();',value='Create Radio Button')
3
votes

Dynamically created radio button in javascript:

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”RadioDemo.aspx.cs” Inherits=”JavascriptTutorial.RadioDemo” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title></title>
<script type=”text/javascript”>

/* Getting Id of Div in which radio button will be add*/
var containerDivClientId = “<%= containerDiv.ClientID %>”;

/*variable count uses for define unique Ids of radio buttons and group name*/
var count = 100;

/*This function call by button OnClientClick event and uses for create radio buttons*/
function dynamicRadioButton()
{
/* create a radio button */
var radioYes = document.createElement(“input”);
radioYes.setAttribute(“type”, “radio”);

/*Set id of new created radio button*/
radioYes.setAttribute(“id”, “radioYes” + count);

/*set unique group name for pair of Yes / No */
radioYes.setAttribute(“name”, “Boolean” + count);

/*creating label for Text to Radio button*/
var lblYes = document.createElement(“lable”);

/*create text node for label Text which display for Radio button*/
var textYes = document.createTextNode(“Yes”);

/*add text to new create lable*/
lblYes.appendChild(textYes);

/*add radio button to Div*/
containerDiv.appendChild(radioYes);

/*add label text for radio button to Div*/
containerDiv.appendChild(lblYes);

/*add space between two radio buttons*/
var space = document.createElement(“span”);
space.setAttribute(“innerHTML”, “&nbsp;&nbsp”);
containerDiv.appendChild(space);

var radioNo = document.createElement(“input”);
radioNo.setAttribute(“type”, “radio”);
radioNo.setAttribute(“id”, “radioNo” + count);
radioNo.setAttribute(“name”, “Boolean” + count);

var lblNo = document.createElement(“label”);
lblNo.innerHTML = “No”;
containerDiv.appendChild(radioNo);
containerDiv.appendChild(lblNo);

/*add new line for new pair of radio buttons*/
var spaceBr= document.createElement(“br”);
containerDiv.appendChild(spaceBr);

count++;
return false;
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<asp:Button ID=”btnCreate” runat=”server” Text=”Click Me” OnClientClick=”return dynamicRadioButton();” />
<div id=”containerDiv” runat=”server”></div>
</div>
</form>
</body>
</html>

(source)

1
votes

Quick reply to an older post:

The post above by Roundcrisis is fine, IF AND ONLY IF, you know the number of radio/checkbox controls that will be used before-hand. In some situations, addressed by this topic of 'dynamically creating radio buttons', the number of controls that will be needed by the user is not known. Further, I do not recommend 'skipping' the 'try-catch' error trapping, as this allows for ease of catching future browser implementations which may not comply with the current standards. Of these solutions, I recommend using the solution proposed by Patrick Wilkes in his reply to his own question.

This is repeated here in an effort to avoid confusion:

function createRadioElement( name, checked ) {
   var radioInput;
   try {
        var radioHtml = '<input type="radio" name="' + name + '"';
        if ( checked ) {
            radioHtml += ' checked="checked"';
        }
        radioHtml += '/>';
        radioInput = document.createElement(radioHtml);
    } catch( err ) {
        radioInput = document.createElement('input');
        radioInput.setAttribute('type', 'radio');
        radioInput.setAttribute('name', name);
        if ( checked ) {
            radioInput.setAttribute('checked', 'checked');
        }
    }
    return radioInput;}
1
votes
for(i=0;i<=10;i++){
   var selecttag1=document.createElement("input");
   selecttag1.setAttribute("type", "radio");
   selecttag1.setAttribute("name", "irrSelectNo"+i);
   selecttag1.setAttribute("value", "N");
   selecttag1.setAttribute("id","irrSelectNo"+i);

   var lbl1 = document.createElement("label");
   lbl1.innerHTML = "YES";
   cell3Div.appendChild(lbl);
   cell3Div.appendChild(selecttag1);
}
0
votes

My suggestion is not to use document.Create(). Better solution is to construct actual HTML of future control and then assign it like innerHTML to some placeholder - it allows browser to render it itself which is much faster than any JS DOM manipulations.

Cheers.

0
votes

Patrick's answer works, or you can set the "defaultChecked" attribute too (this will work in IE for radio or checkbox elements, and won't cause errors in other browsers.

PS Full list of attributes you can't set in IE is listed here:

http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html

0
votes

why not creating the input, set the style to dispaly: none and then change the display when necesary this way you can also probably handle users whitout js better.