views:

489

answers:

3

Hello SO:

I have this javascript that adds a form field, along with a link to remove that field:

var fieldCount = 0;
function addField() {
    var name = 'file' + fieldCount;
    var row = 'row' + fieldCount;
    var str = '<p id="' + row + '"><label for="' + name + '">File to upload: <input type="file" name="' + name + '" id="' + name + '" />(100MB max size) <a onclick="removeRow(' + row + '); return false;">[-]</a></label></p>';
    fieldCount++;
    $("#fields").append(str);
};
function removeRow(id) {
    $(id).remove();
};

Here is the markup:

<form id="ajaxUploadForm" action="<%= Url.Action("AjaxUpload", "Upload")%>" method="post" enctype="multipart/form-data">
    <fieldset id="uploadFields">
        <legend>Upload a file</legend>
        <div id="fields"></div>
        <input id="ajaxUploadButton" type="submit" value="Submit" />            
    </fieldset>
    <a onclick="addField(); return false;" id="add">Add</a>
    <div id="resultBox">
        <p id="status" style="margin:10px;"></p>
    </div>
</form>

The addFields works as expected, but when I click the remove link firebug tells me that "row#" is not defined, where # is any number of the added fields.

Any help would be appreciated!

+2  A: 

You need to have quotes around it, since it's a string. You also need the "#" to make it into a selector:

var str = '... <a onclick="removeRow(\'#' + row + '\'); return false;">...';

A better way would be to assign the onclick as a function (not sure of the jQuery way to do this but in plain Javascript):

var a = document.createElement('a');
a.onclick = (function(row)
{
    return function()
    {
        removeRow(row);
        return false;
    };
})();
Greg
I like this response because it seems to adhere better to the spirit of unobtrusive JavaScript. Even though both solutions are scripted outside of the static HTML, the ops solution renders HTML with inline JavaScript whereas your solution is truly separated from the HTML.
Mayo
+4  A: 

You need to pass a valid selector expression for an ID selector (#ID), either in the removeRow call (also note the quotes surrounding the ID selector):

'<a onclick="removeRow(\'#' + row + '\'); return false;">'

Or in the removeRow function itself:

function removeRow(id) {
    $("#" + id).remove();
};
Gumbo
At least I was on the right track with my own answer - just didn't type it in time. :)
Mayo
Ah, I definitely forgot the #. Thanks!
Anders
+2  A: 

You are passing in the string value of "row12", but the selector should be:

$('#'+row').remove()

The # specifies that you are looking for an ID. I agree with what I think one of the other answers was about to say, you should just use the onclick events' natural "this" keyword instead:

<p onclick="remove(this)">something</p>

function remove(what) {
 $(what).remove()
}

Or, maybe just forget the whole thing all together and switch to a behavior for those kinds of rows:

$('.removableRow').live('click', function() {$(this).remove()});

Then you just specify that the row is removable, and never have to worry about binding events at all:

<p><a class="removableRow" href="#">Remove</a></p>
altCognito
Unfortunately with this, if I click the browse... button, it will remove the row. Is there a way to just accept the click from the anchor tag?
Anders
Sure, I changed it up to show what you asked for.
altCognito