49

So I have a bunch of paragraph elements which are dynamically populated from a db. I have made the elements contenteditable. I now want to submit edits back the the db via a standard form submission. Is there a way to post the contenteditable elements back?

Jason Sundram
  • 12,225
  • 19
  • 71
  • 86
MFB
  • 19,017
  • 27
  • 72
  • 118

4 Answers4

42

You have to use javascript one way or the other, it won't work as a "standard" form element as it would with a textarea or the like. If you like, you could make a hidden textarea within your form, and in the form's onsubmit function copy the innerHTML of the contenteditable to the textarea's value. Alternatively you could use ajax/xmlHttpRqeuest to submit the stuff a bit more manually.

function copyContent () {
    document.getElementById("hiddenTextarea").value =  
        document.getElementById("myContentEditable").innerHTML;
    return true;
}


<form action='whatever' onsubmit='return copyContent()'>...
Jason Sundram
  • 12,225
  • 19
  • 71
  • 86
rob
  • 9,933
  • 7
  • 42
  • 73
  • 2
    It seems it is better to use `innerText`, or you'll get put all invisible markup into textarea. – denis.peplin Mar 10 '17 at 19:24
  • 2
    That's the point. You need all that markup, why else would you use a contentEditable? Remember the textarea is hidden, it is just used to hold the contents prior to sending it to the server. – rob Mar 10 '17 at 23:00
2

If anyone is interested I patched up a solution with VueJS for a similar problem. In my case I have:

<h2 @focusout="updateMainMessage" v-html="mainMessage" contenteditable="true"></h2>
<textarea class="d-none" name="gift[main_message]" :value="mainMessage"></textarea>

In "data" you can set a default value for mainMessage, and in methods I have:

methods: {
  updateMainMessage: function(e) {
    this.mainMessage = e.target.innerText;
  }
}

"d-none" is a Boostrap 4 class for display none. Simple as that, and then you can get the value of the contenteditable field inside "gift[main_message]" during a normal form submit for example, no AJAX required. I'm not interested in formatting, therefore "innerText" works better than "innerHTML" for me.

Alberto T.
  • 487
  • 3
  • 8
0

Does it NEED to be standard form submission? If you cannot or do not want use a form with inputs, you may try AJAX (XMLHttpRequest + FormData), through which you could perform asynchronous requests and control better how response shows up.

If you want it even simpler, try jQuery's $.ajax function (also $.get and $.post). It sends data using simple JS objects.

Johannes Müller
  • 5,581
  • 1
  • 11
  • 25
  • An example of XHR working with FormData: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects –  Oct 10 '17 at 20:19
0

Made a fully working example based on Rob's idea:

After hitting submit, the (hidden) textarea is updated with the table-data, in JSON-format.
(return true to submit)

function copyContent() {
  const table = [];
  $("tr").each(function() {
    const row = [];
    $("th, td", this).each(function() {
      row.push($(this).text());
    });
    table.push(row);
  });
  $("#rows").val(JSON.stringify(table));

  // return true to submit
  return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form onsubmit='return copyContent()'>
  <textarea name="rows" id="rows" rows="4"></textarea>
  <button type="submit">Submit</button>
</form>

<table class="table table-striped">
  <thead>
    <tr>
      <th>Head 1</th>
      <th>Head 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td contenteditable="true">edit </td>
      <td contenteditable="true">me</td>
    </tr>
    <tr>
      <td contenteditable="true">please</td>
      <td contenteditable="true"></td>
    </tr>
  </tbody>
</table>
Aldo
  • 730
  • 8
  • 20