1

I am trying to add event listeners to my viewmodel once VueJS is loaded. Adding event listeners works if I do not use VueJS, so I know the code is correct but they never attach in VueJS.

<div id="app">
  <div name="pageContent" id="preview">
    <section class="row">
      <div class="columns medium-12">
        <h1>This is the top content</h1>
        <p>ashcbaubvdiuavduabd</p>
      </div>
    </section>
    <section class="row">
      <div class="columns medium-6">
        <h1>This is left content</h1>
        <p>ashcbaubvdiuavduabd</p>
      </div>
      <div class="columns medium-6">
        <h1>This is the right content</h1>
        <p>ashcbaubvdiuavduabd</p>
      </div>
    </section>
  </div>
</div>
<script type="text/javascript">
  let editorContainer = document.getElementById('preview')
  let controls = document.getElementById('defaultControls')
  let cmsEditor = new CmsEditor(editorContainer, controls)
  var app = new Vue({
    el: '#app',
    data: {
      editor: cmsEditor
    },
    mounted: function () {
      // wire up our listeners
      console.log('mounted')
      document.oncontextmenu = function () { return false }
      let rows = this.editor.EditorContainer.getElementsByTagName('section')
      for (var i = 0; i < rows.length; i++) {
        console.log('section ' + i + ' : ' + rows[i].innerHTML)
        rows[i].addEventListener('mouseover', function () {
          console.log('mouse over event')
          this.editor.SetActiveRow(this)
        })
        rows[i].addEventListener('dblclick', function () {
          this.editor.DisplayContextMenu(this)
        })
      }
    },
    methods: {
      save: function () {
        console.log('save')
        this.editor.Save()
      },
      undo: function () {
        console.log('undo')
        this.editor.Undo()
      }
    }
  })
</script>
Bouke Versteegh
  • 4,097
  • 1
  • 39
  • 35
Slee
  • 27,498
  • 52
  • 145
  • 243
  • Events in Vue are different from DOM events. You are not registering any Vue events. Your callbacks aren't working because you're accessing the wrong `this`. – thanksd Sep 13 '17 at 15:07
  • 1
    Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – thanksd Sep 13 '17 at 15:07
  • If you are using ES6, use the arrow function so that the lexical `this` (i.e that of the VueJS instance) is bound. Otherwise, you will have to cache it outside the event listener, e.g. `var self = this` so that within the event listener you can refer to your Vue instance correctly, e.g. `self.editor.SetActiveRow(this)`. – Terry Sep 13 '17 at 15:25
  • self.editor.SetActiveRow(this) is not the issue, the listener onmouseover is not being set at all, even if I just put console logs in there they do not get called. If I inspect the document for events on those elements and they are non existent. addEventListener is not attaching a listener at all. – Slee Sep 13 '17 at 20:21

1 Answers1

3

Looks like you are creating the editor on elements that will be removed from the DOM. Vue uses the content of #app as it's template, compiles the template into a render function, then replaces the DOM with the results of the render function. Given that editor is created on DOM elements that are gone now, I expect the code would fail.

You probably want to move the creation of the editor into mounted, then set up your event listeners.

FWIW, I also think you have the this issue mentioned by the commenters.

I think it should be something like this:

  mounted: function() {
    let editorContainer = document.getElementById('preview');
    let controls = document.getElementById('defaultControls');
    this.editor = new CmsEditor(editorContainer, controls);
  
    // wire up our listeners
    console.log('mounted')
    document.oncontextmenu = function () { return false; };
    let rows = this.editor.EditorContainer.getElementsByTagName("section");
    for (var i = 0; i < rows.length; i++) {
      console.log("section " + i + " : " + rows[i].innerHTML);
      rows[i].addEventListener('mouseover', () => {
        console.log('mouse over event');
        this.editor.SetActiveRow(this);
      });
      rows[i].addEventListener('dblclick', () => {
        this.editor.DisplayContextMenu(this);
      });
    }
  },
Bouke Versteegh
  • 4,097
  • 1
  • 39
  • 35
Bert
  • 80,741
  • 17
  • 199
  • 164