-3
$('#attachments').append("<tr><td><b>Attachment " + next + "</b><input id='upload" + next + "'name='files'" + "onchange='showUpload('" + next + "') type='file' value='System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]'></td></tr>");

The above code is printing the following in the browser. What am I doing wrong?

<input id="upload1" name="files" onchange="showUpload(" 1') type="file" value="System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]" class="valid" aria-invalid="false">

onchange="showUpload(" 1') needs to be onchange="showUpload('1')

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • 3
    This would be significantly easier if you use string interpolation instead of concatenation. To answer your question, you're clearly mismatching your quotes. –  Dec 28 '17 at 20:25
  • 2
    You will need some escaping here and I personally would stick with the rule to use double quotes for html attributes and single quotes in javascript. – AlvaHenrik Dec 28 '17 at 20:27
  • I do not see how that generates those quotes....Seems sort of impossible.... – epascarello Dec 28 '17 at 20:28
  • I agree with @Amy - you would have better luck utilizing template literals than concatenating as you are. Also they allow for spacing like a `heredoc` which would greatly benefit the readability of your code. – zfrisch Dec 28 '17 at 20:29
  • Please do not vandalise questions, especially not after they received answers. – Yunnosch Dec 16 '21 at 14:32

3 Answers3

3

I recommend using string interpolation (template literals) instead. To find out if your browser supports template literals, check Can I Use.

It's far easier to get this right. I've added newlines so it's readable. Making your HTML on one line like that is just impossible to read:

var content = `<tr><td>
                   <b>Attachment ${next}</b>
                   <input id="upload${next}"
                          name="files"
                          onchange="showUpload('${next}')"
                          type="file"
                          value="snipped for brevity">
               </td></tr>`;

 $('#attachments').append(content);

What this does is fairly intuitive: the template literal, delineated by backticks, will replace each instance of ${next} with the value in the next variable.

I have also taken the liberty to change all of your attributes to use double quotes for consistency. Hopefully I didn't make any typos.

  • And hopefully the browser's they are required to support has support for it. – epascarello Dec 28 '17 at 20:33
  • As an aside, the tag `b` is deprecated and should be replaced with `strong`. – zfrisch Dec 28 '17 at 20:34
  • @epascarello added comment to that effect and a link to the Can I Use page for ES6 template literals. –  Dec 28 '17 at 20:35
  • @zfrisch actually it's only deprecated for *styling*. It's still current for relaying semantic information. –  Dec 28 '17 at 20:43
  • @Amy totally true, but I've honestly never seen it used for semantic markup because why would you given that it will most likely still add styling? Haha. But you are right and it's possible that was the OPs intention. – zfrisch Dec 28 '17 at 20:48
  • This works wonderfully. @Amy, thank you for taking the time to show this solution. I apologize for the original question and its formatting. Know better, do better. I know better for next time. –  Dec 28 '17 at 20:50
  • @DevNoob My pleasure. To be frank, I don't think you have anything to apologize for. Welcome to Stack Overflow. –  Dec 28 '17 at 21:31
2

Superficially "onchange='showUpload('" closes the onchange value before the function's parameter, which leads to malformed HTML.

What am I doing wrong?

What you're really doing wrong is that you're adding inline event handlers with jQuery, which leads to problems exactly like that.

var tr = $("<tr><td><b>Attachment " + next + "</b></td></tr>").appendTo("#attachments");

$('<input>', {
  id: "upload" + next,
  name: "files",
  type: "file",
  value: "System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]"
}).on( 'change', function() { showUpload(next); } )
  .appendTo(tr.find('td'));
JJJ
  • 32,902
  • 20
  • 89
  • 102
0

You can simply escape a character

    $('#attachments')
  .append("<tr><td><b>Attachment " + next + "</b><input id='upload" + next + "' name='files'  onchange='showUpload(\"" + next + "\")' type='file' value='System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]'></td></tr>");
Denis Rybalka
  • 1,821
  • 3
  • 18
  • 28