25

I have what I think is a very common scenario. I would normally have this form:

<form method="post">

<textarea name="text"></textarea>
<input type="submit" value="Save" />

</form>

Then with PHP I would capture the data from the form ($_POST['text']) and I could use that in another variable.

Now, I'd like to use Quill so users have a nice rich text editor instead. Quill seems very well suited for this and the documentation is very detailed. However, for some reason I can not find how I can "post" the data to the form. There is one single sample page that sort of does what I want, but I am unable to fully implement this in my sample, and in the quick start guide this rather fundamental (to me) topic is not discussed, and I can not find this in the documentation either.

Is Quill supposed to be used like this? Am I overseeing something? Is there a recommended way to make this work?

This is what I currently have:

<!doctype html>
<html>
<head>
<title>Test</title>
<meta charset="UTF-8" />
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">
</head>
<body>
<form method="post">


<!-- Create the toolbar container -->
<div id="toolbar">
  <button class="ql-bold">Bold</button>
  <button class="ql-italic">Italic</button>
</div>


<form method="post">

<!-- Create the editor container -->
<div id="editor">
  <p>Hello World!</p>
</div>

<input type="submit" value="Save" />

</form>

<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>

<!-- Initialize Quill editor -->
<script>
  var editor = new Quill('#editor', {
    modules: { toolbar: '#toolbar' },
    theme: 'snow'
  });
</script>
</body>
</html>
user32421
  • 689
  • 3
  • 8
  • 19
  • 1
    I've continued researching this and it seems like Quill was not really made for this (https://github.com/quilljs/quill/issues/774). It really and sadly seems that Quill is not a good solution for having users type rich text and saving the HTML in a database. But I'm still not fully understanding why or if this is really the case, so if someone can shed light on the situation please do. – user32421 Jun 10 '17 at 14:33
  • Here's a more recent discussion (https://github.com/quilljs/quill/issues/1234). The suggestion is to save the innerHTML and the deltas array. [To post the innerHTML see this answer](https://stackoverflow.com/a/38426793/3585500) but replace `var question = advancedEditor.getText()` with `editor.container.innerHTML`. – ourmandave Jun 11 '17 at 01:12

15 Answers15

38
<form method="post" id="identifier">

  <div id="quillArea"></div>

  <textarea name="text" style="display:none" id="hiddenArea"></textarea>
  <input type="submit" value="Save" />

</form>

If you give the form an identifier, then using jQuery you can do the following:

var quill = new Quill ({...}) //definition of the quill

$("#identifier").on("submit",function() {
  $("#hiddenArea").val($("#quillArea").html());
})

Instead of the HTML you could use quill.getContents() to get the delta.

ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
GazEdBro
  • 349
  • 3
  • 6
  • 5
    If you want to get only the content, you can add `.ql-editor` to your selector : `$("#hiddenArea").val($("#quillArea .ql-editor").html());` – Adrien V Jul 30 '20 at 16:38
  • 1
    When using getContents() to retrieve the deltas, you should also stringify it to json else, [Object object] is sent. `$("#hiddenArea").val(JSON.stringify(quill.getContents()))` – naghal May 26 '21 at 21:00
27

You can check related discussion about it https://github.com/quilljs/quill/issues/87

While this is not an ideal solution :

var myEditor = document.querySelector('#editor')
var html = myEditor.children[0].innerHTML
erw13n
  • 474
  • 5
  • 12
  • 27
    Thanks. Why is this so difficult? What is the purpose of Quill if this kind of thing is so difficult to achieve? – user32421 Jun 12 '17 at 21:38
  • 2
    This answer appears to be pretty simple... +1 – Mike Barwick Sep 11 '17 at 22:19
  • 1
    This is how I approached it before looking to Google for a solution. Seems pretty straight forward. – germs12 Dec 12 '18 at 14:13
  • 1
    The question for me is the same. They have created so amazing tool which have been not done by anyone for so many years. But they are not telling how to get data to form and post it! What is the essence of this plugin :) Smart! Not! – Gediminas Šukys Feb 12 '20 at 14:16
  • Does it answer to the question and adds all content to a provided text field? I can't see any method for that in the answer. Only gathering data. Thanks! – Gediminas Šukys Feb 12 '20 at 14:22
9

Here's the code I used to do this:

$(document).ready(function(){
  $("#theform").on("submit", function () {
    var hvalue = $('.ql-editor').html();
    $(this).append("<textarea name='content' style='display:none'>"+hvalue+"</textarea>");
   });
});

Basically, what it does is to add a hidden textarea to your form and copy the content of the "ql-editor" container (This is automatically made by Quill Editor in the container div) to it. The textarea will then be submitted with the form. You need to change the IDs used in the code to the id of your container tags.

eLeMeNOhPi
  • 251
  • 2
  • 5
9

I'm doing this:

var quill = new Quill('.quill-textarea', {
            placeholder: 'Enter Detail',
            theme: 'snow',
            modules: {
                toolbar: [
                    ['bold', 'italic', 'underline', 'strike'],
                    [{ 'list': 'ordered'}, { 'list': 'bullet' }],
                    [{ 'indent': '-1'}, { 'indent': '+1' }]
                ]
            }
        });

        quill.on('text-change', function(delta, oldDelta, source) {
            console.log(quill.container.firstChild.innerHTML)
            $('#detail').val(quill.container.firstChild.innerHTML);
        });

Somewhere on the form:

<div class="quill-textarea"></div>
<textarea style="display: none" id="detail" name="detail"></textarea>
Emeka Mbah
  • 16,745
  • 10
  • 77
  • 96
5

A solution I came up with was to make a wrapper class.

class QuillWrapper {

    /**
     * @param targetDivId { string } The id of the div the editor will be in.
     * @param targetInputId { string } The id of the hidden input
     * @param quillOptions { any } The options for quill
     */
    constructor(targetDivId, targetInputId, quillOptions) {

        //Validate target div existence
        this.targetDiv = document.getElementById(targetDivId);
        if (!this.targetDiv) throw "Target div id was invalid";

        //Validate target input existence
        this.targetInput = document.getElementById(targetInputId);
        if (!this.targetInput) throw "Target input id was invalid";

        //Init Quill
        this.quill = new Quill("#" + targetDivId, quillOptions);

        //Bind the two containers together by listening to the on-change event
        this.quill.on('text-change',
            () => {
                this.targetInput.value = this.targetDiv.children[0].innerHTML;
            });
    }
}

Simply include the class somewhere on your page and then use the following to initilize it:

    let scopeEditor = new QuillWrapper("ScopeEditor", "Scope", { theme: "snow" });

Your html would look roughly like this:

<div class="form-group">
     <label asp-for="Scope" class="control-label col-md-2"></label>  
     <div id="ScopeEditor"></div>
     <input type="hidden" asp-for="Scope" class="form-control" />
</div>
Maxwell
  • 51
  • 1
  • 3
3

I know this problem has already been resolved, but I would like to add a little more information. To obtain the data present in Quill, You don't need jQuery, or a different trick. I recommend looking at this answer:

https://stackoverflow.com/a/42541886/2910546

I should also make a note here: The author's question was asked at least 2 years ago. So, today, I believe this is to be the most viable way to address the question.

For more information on Quill, with case study examples, and common questions with answers, please kindly visit the following link:

https://github.com/loagit/Quill-Examples-and-FAQ

Loa
  • 2,117
  • 3
  • 21
  • 45
  • Do you know if it's possible to get the HTML contents, but respecting the new lines as they were in the document initially? Because it seems that, by default, the editor puts all the HTML into a single line as soon as it initializes. – Digital Ninja Jan 20 '20 at 02:35
  • @DigitalNinja I think Quill itself doesn’t have that functionality, but you can get what you want using any HTML Beautifier. There are [online tools](https://www.cleancss.com/html-beautify/) that are capable of doing this type of procedure, as well as libraries in javascript such as [highlight js](https://highlightjs.org/). Both can give you the desired result. – Loa Jan 22 '20 at 17:48
1

Solved here

How to save Quill.js values to Database Laravel 5.6

Add a hidden input :

<input type="hidden" name="body"/>

Js code :

var form = document.getElementById("FormId");

form.onsubmit = function() {
  var name = document.querySelector('input[name=body]');
  name.value = JSON.stringify(quill.getContents());

  return true; // submit form
}

To set contents to quill do this :

quill.setContents({!! $post->body !!});
ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
ztvmark
  • 1,319
  • 15
  • 11
1

this is what i use, all you have to do is to provide data-name attribute to your editor tag. this will create a hidden input as sibling to your editor tag and put the html contents inside. you can get other formats of your contents, i leaved unused variables if you need to know how to get them.

html:

<div class="field editor" data-name="experience"></div>

js:

let quill_element = document.querySelector('.editor')
let quill = new Quill(quill_element, {
    modules: {
        toolbar: '#toolbar'
    },
    placeholder: document.querySelector('.editor').getAttribute('data-placeholder'),
    theme: 'bubble',
});

let hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = quill_element.getAttribute('data-name');
quill_element.parentElement.appendChild(hiddenInput);

quill.on('text-change', function () {
    let justHtml = quill.root.innerHTML;
    hiddenInput.value = justHtml;
    // other formats if you like to use..
    var delta = editor.getContents();
    var text = editor.getText();
});
Pezhvak
  • 9,633
  • 7
  • 29
  • 39
1

I found that prevoius solutions on the page also copied a lot of quiill markup html at the end of the field when copied to a hidden field.

The solution described on this page seems to recitfy that:

https://lucidar.me/en/rich-content-editor/how-to-get-html-content-from-quill-rich-editor/

Basically, access the pure HTML with:

var html = quil.root.innerHTML
document.getElementById("descriptionHidden").value = html;
petworthnick
  • 205
  • 2
  • 11
0

Try this:

<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>

<!-- Initialize Quill editor -->
<script>
    var quill = new Quill('#editor', {
        modules: {
            toolbar: [
                ['bold', 'italic'],
                ['link', 'blockquote', 'code-block', 'image'],
                [{
                    list: 'ordered'
                }, {
                    list: 'bullet'
                }]
            ]
        },
        placeholder: 'Compose an epic...',
        theme: 'snow'
    });

    $("#form").submit(function() {
        $("#description").val(quill.getContents());
    });
</script>
Erich García
  • 1,648
  • 21
  • 30
0

this solution works fine for me:

    <script type="text/javascript">
    $(document).ready(function(){
      $("#emailForm").on("submit", function () {
        var hvalue = $('.editor').text();
        $(this).append("<textarea name='message' style='display:none'>"+hvalue+"</textarea>");
       });
    });
    </script>
Mahmoud
  • 167
  • 2
  • 7
0

I solved this problem as follows.

In the element that will be the editor's container, I set a like attribute, data-input-name="something"

and after instantiating the editor I just made a simple code that assigns the internal value of the quill to hidden input

quill.on('text-change', function() {
  const content = quill.root.innerHTML.trim();
  const targetId = quill.container.dataset.inputName
  document.querySelector(`#${targetId}`).setAttribute("value", content);
});
ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
0

Checkout this repo, it might be helpful. It's easy to install.

https://github.com/tangien/quilljs-textarea

AutoInitialize Quilljs simply by adding the attribute data-quilljs to the textarea element and the rest the plugin will take care of it.

Thats it!

0

Try this for your post content Add a div to your form with class selector="basic-quill" and attribute data-id="yourInputName" .

Once the page loads, call the quill_editor_load function and you're done.

When you submit the form and retrieve the data with PHP or jQuery, make sure it is available with the name "yourInputName".

function quill_editor_load() {
  var quill_element = '.basic-quill',
    parent_form;
  if ($(quill_element).length) {
    if (typeof $(quill_element).attr("data-id") !== 'undefined' && typeof $(quill_element).attr("data-name") !== 'undefined') {
      var place_holder = (typeof $(quill_element).attr("data-placeholder") !== 'undefined' ? $(quill_element).attr("data-placeholder") : "Enter your text here");
      var quillElementId = (($(quill_element).attr("data-id").substring(0, 1) != '#') ? $(quill_element).attr("data-id") : $(quill_element).attr("data-id").substring(1, $(quill_element).attr("data-id").length));
      if (typeof $(quill_element).attr("id") === 'undefined') {
        $(quill_element).attr("id", quillElementId);
      }
      var quill = new Quill('#' + quillElementId, {
        modules: {
          toolbar: [
            [{
              header: [1, 2, false]
            }],
            ['bold', 'italic', 'underline', 'strike'],
            ['link', 'image', 'code-block'],
            [{
              'list': 'ordered'
            }, {
              'list': 'bullet'
            }],
          ]
        },
        placeholder: place_holder,
        theme: 'snow' // or 'bubble'
      });
      var input = $('input[name="' + quillElementId + '"]');
      parent_form = $(quill_element).parents('form');
      if (!input.length) {
        if (parent_form.length) {
          input = parent_form.append('<input type="hidden" id="' + quillElementId + '" name="' + quillElementId + '" value="">').find('input[name="' + quillElementId + '"]');
        }
      }
      input.val(quill.root.innerHTML);
      quill.on('text-change', function(delta, oldDelta, source) {
        input.val(quill.container.firstChild.innerHTML);
      });
    }
  }
}

$(function() {
  quill_editor_load();
  $('form#quillForm').on('submit', function(e) {
    var formData = new FormData($('form#quillForm')[0]);
    formData.forEach(function(item, idx) {
      console.log(idx + ':', item);
    });
    e.preventDefault();
  });
});
<!doctype html>
<html>

<head>
  <link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">
</head>

<body>
  <form id="quillForm">
    <div>
      <label>Title</label>
      <input type="text" name="title">
    </div>
    <br/>
    <div>
      <label>Description</label>
      <div class="basic-quill" data-id="#txt_description" data-placeholder="Description" data-name="description">
        <h1>This is a heading text...</h1>
        <br/>
        <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla dui arcu, pellentesque id mattis sed, mattis semper erat. Etiam commodo arcu a mollis consequat. Curabitur pretium auctor tortor, bibendum placerat elit feugiat et. Ut ac turpis nec
          dui ullamcorper ornare. Vestibulum finibus quis magna at accumsan. Praesent a purus vitae tortor fringilla tempus vel non purus. Suspendisse eleifend nibh porta dolor ullamcorper laoreet. Ut sit amet ipsum vitae lectus pharetra tincidunt. In
          ipsum quam, iaculis at erat ut, fermentum efficitur ipsum. Nunc odio diam, fringilla in auctor et, scelerisque at lorem. Sed convallis tempor dolor eu dictum. Cras ornare ornare imperdiet. Pellentesque sagittis lacus non libero fringilla faucibus.
          Aenean ullamcorper enim et metus vestibulum, eu aliquam nunc placerat. Praesent fringilla dolor sit amet leo pulvinar semper. </p>
      </div>
    </div>
    <br/>
    <button type="submit">Submit</button>
  </form>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>
</body>

</html>
MIA
  • 11
  • 1
  • 2
  • Answer needs supporting information Your answer could be improved with additional supporting information. Please [edit](https://stackoverflow.com/posts/76223506/edit) to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](https://stackoverflow.com/help/how-to-answer). – moken May 12 '23 at 11:46
-1

Link CSS:

<!-- CSS Implementing Plugins -->
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/css/vendor.min.css">
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/vendor/bootstrap-icons/font/bootstrap-icons.css">
<!-- CSS Front Template -->
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/css/theme.min.css?v=1.0">

Link JS:

<!-- JS Implementing Plugins -->
<script src="https://htmlstream.com/preview/front-v4.2/html/assets/js/vendor.min.js"></script>
<!-- JS Front -->
<script src="https://htmlstream.com/preview/front-v4.2/html/assets/js/theme.min.js"></script>

En mi html:

<form id="form-perfil" name="form-perfil" method="POST">
  <!-- Form Group -->
  <div class="row form-group">
    <label class="col-sm-3 col-form-label input-label">BIO</label>

    <div class="col-sm-9">
      <!-- Quill -->
      <div class="quill-custom">
        <div
          class="js-quill"
          style="min-height: 15rem;"
          data-hs-quill-options='{
                       "placeholder": "Type your message...",
                        "modules": {
                          "toolbar": [
                            ["bold", "italic", "underline", "strike", "link", "image", "blockquote", "code", {"list": "bullet"}]
                          ]
                        }
                       }'
        >
          Creative mind at Htmlstream
        </div>
      </div>
      <!-- End Quill -->
      <textarea name="text_quill" style="display: none;" id="text_quill"></textarea>
    </div>
  </div>
  <!-- End Form Group -->

  <button type="submit" class="mt-3 float-right btn btn-primary">Enviar formulario</button>
  <!-- End Form Group -->
</form>

En mi JS:

// INITIALIZATION OF QUILLJS EDITOR
// =======================================================
var quill = $.HSCore.components.HSQuill.init('.js-quill');

// =======================================================
$("#form-perfil").on("submit", function (e) { 
  e.preventDefault(); //No se activará la acción predeterminada del evento

  $("#text_quill").val($(".ql-editor").html());

  var formData = new FormData($("#form-perfil")[0]);
  $.ajax({
    url: "ajax/pago_administrador.php",
    type: "POST",
    data: formData,
    contentType: false,
    processData: false,
    success: function (datos) {  },             
  });
});
  • This answer does not provide anything new that other answers have not covered and also does not include any explanation as to the what the code is meant to do. – Besworks Apr 05 '22 at 14:49