Bind to an Element Which Does Not Exist (with no user interaction/click)

Viewed 28

I've been added to an existing project (jQuery, petite-vue ...) and I'm trying to add this simple WYSIWYG to a form textarea.

The textarea does not exist on page load. This is the template code which shows how it's added dynamically. The forum object is the result of an async GET wait fetch request.

<div class="row" v-if="forum.currentGroup && JSON.stringify(forum.currentGroup) != '{}'">
    <div class="col-md-12 mb-2">
        <form @submit.prevent="forum.addThread" method="post" class="no-recaptcha mb-2">
            <textarea rows="4"
                      id="summernote"
                      name="question"
                      placeholder="{{ 'forum.ask_your_question' | trans }}"
                      class="form-control mb-2 question"
                      required></textarea>
            <button type="submit" class="btn btn-primary small float-end">{{ 'forum.send' | trans }}</button>
        </form>
    </div>
</div>

As per the summernote install direction, the following command simply doesn't work;

    $(document).ready(function() {
        $('#summernote').summernote();
    });

I also tried to access the element when receiveing a response from the fetch request, but it is always logging null in the code below;

        try {
            let response = await fetch(` ... the url ... `, {
                method: 'GET',
            });

            if (response.ok) {
                const json = await response.json();
                if (json.success) {
                    ...

                    let thing = document.getElementById('summernote');
                    console.log(thing);

                    $('#summernote').summernote();

To try and find out what's going on with the document, I ran the following code;

    window.addEventListener('load', (event) => {
        console.log('load');
    });

    document.addEventListener('readystatechange', (event) => {
        console.log(document.readyState);
    });

    document.addEventListener('DOMContentLoaded', (event) => {
        console.log('DOMContentLoaded');
    });

The console log for that code is;

complete
load

The DOMContentLoaded listener never outputs to console. I tried using an on('load') but it never gets called;

    $(document).on('load', '.question', function() {
        alert('blah');
        $('#summernote').summernote();
    });

I have to render the WYSIWYG without user interaction ... when the textarea is added to the page, it should render the wysiwyg editor.

Any ideas? I've been at this for a couple of days and am at a loss.

1 Answers

Create a custom component with the <textarea> inside, and initialise the plugin on mount:

const SummernoteView = {
    mounted() {
        $("#summernote").summernote();
    },
    template: `
        <textarea rows="4"
            id="summernote"
            name="question"
            placeholder="{{ 'forum.ask_your_question' | trans }}"
            class="form-control mb-2 question"
            required></textarea>
    `,
};

export default SummernoteView;

Remember to import and declare it in the parent component:

import SummernoteView from './SummernoteView';

// your parent component
{
  data() { ... },
  methods: { ... }
  components: {
    'summernote-view': SummernoteView
  }
}

In your template:

<div class="row" v-if="forum.currentGroup && JSON.stringify(forum.currentGroup) != '{}'">
    <div class="col-md-12 mb-2">
        <form @submit.prevent="forum.addThread" method="post" class="no-recaptcha mb-2">
            <summernote-view/>
            <button type="submit" class="btn btn-primary small float-end">{{ 'forum.send' | trans }}</button>
        </form>
    </div>
</div>

More on Vue Components.

Related