2

I am trying to loop through an array of objects, which depending on their type property, will create a different class and append it to an array. The problem is that the output is always just a list of duplicates of the last class created.

// Create Elements from Content
// The id's are created by UUIDV4 and are all different.
self._elements = new Array

let e;
self.content.page_data.forEach(cont => {
    switch (cont.type) {
        case 'paragraph':
            e = new Paragraph()
            console.log(e.element.id)
            self._elements.push(e)  
            break;

        case 'title':
            console.log('title')
        return 
    }
})
console.log(self._elements)

After troubleshooting I've found that the problem isn't e, as each instance is different, however once it is pushed / added to the array, the problem occurs. The problem only occurs when instances of Paragraph() are created. As other items in the array, like text, will remain the same while still duplicating the last class.

Please can someone explain what I'm missing here?

EDIT - Class for Paragraph

class Paragraph {
  constructor(value = '') {

    self._element = template_paragraph.cloneNode(true).content.children[0];
    const quil = self._element.children[0].children[1].children[0];
    self.quill = new Quill(quil, {
      modules: {
        toolbar: [
          [{ header: [1, 2, false] }],
          ['bold', 'italic', 'underline'],
          [{ list: 'ordered' }, { list: 'bullet' }]
        ]
      },
      placeholder: 'Compose an epic...',
      theme: 'snow'  // or 'bubble'
    })

    self._element.id = uuidv4()
  }

  get element() {
    return self._element
  }

  set_content(content) {
    // Set quill value
    if (!content) return
    //self.quill.setContents(content)
  }
}

The quill interacts with my html clone as intended. I hope this will help.

Wyck
  • 5,985
  • 4
  • 34
  • 44
HarrowXY
  • 23
  • 6
  • have you tried pushing directly the instance without passing by a variable, like here: ``` self._elements.push(new Paragraph()) ``` – Ismail Diari Nov 11 '20 at 14:44
  • 2
    What is new Paragraph? My guess is that is the problem. SOunds like that is using the same object reference. It would also be better to declare `e` as a `const` inside the `case` statement instead of a common variable. – epascarello Nov 11 '20 at 14:44
  • @IsmailDiari that had no effect and new Paragraph() is a constructor which clones a template, to fill with a quil.js: `self._element = template_paragraph.cloneNode(true).content.children[0];` and has a getter to get `self._element` – HarrowXY Nov 11 '20 at 14:47
  • @Wyck I still new here and I stuck with all this staff guys :D – Ismail Diari Nov 11 '20 at 14:49
  • @Wyck, no way to edit it anymore (I consumed my three chances) – Ismail Diari Nov 11 '20 at 14:50
  • The behaviour of `cloneNode` is relevant here. What does that do? – Wyck Nov 11 '20 at 15:14
  • It creates a copy of the node (and with true, it's children) https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode – HarrowXY Nov 11 '20 at 15:16
  • I've given you the benefit of the doubt thus far, but it's very interesting that `Paragraph` doesn't use `this` anywhere. Is this just a facepalm where you typed `self` instead of `this`? Are you a Python programmer? – Wyck Nov 11 '20 at 15:27
  • TBH this is my first project in JS using my own classes, I've only ever made them in Python – HarrowXY Nov 11 '20 at 15:28
  • 1
    Yeah, that's your problem then. The keyword is `this` in JavaScript. Not `self` (that's a Python thing.) Since `self` is *not* a keyword in JavaScript, some people use it [by convention](https://stackoverflow.com/q/16875767/1563833) as a normal variable name by manually assigning `var self = this;` somewhere. But really, I think you just want to say `this` and use it [the normal way](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). – Wyck Nov 11 '20 at 15:32
  • Yep... it worked... man... I can't thank you enough. My project was frozen till then, thanks so much. I should probably go re-read on JS object constructors. Thanks again :D – HarrowXY Nov 11 '20 at 15:34
  • This question will likely be closed due to it being basically a "typo" - a wrong keyword error. (You just got confused about the keyword name.) Or at the very least "not reproducible" because you never defined "self") Glad you're all fixed up! cheers. :) – Wyck Nov 11 '20 at 15:35

3 Answers3

1

The keyword is this in JavaScript. Not self (that's a Python thing.) Since self is not a keyword in JavaScript, some people use it by convention as a normal variable name by manually assigning var self = this; somewhere. But really, I think you just want to say this and use it the normal way.

Replace self with this in your code and you should be good to go.

Wyck
  • 5,985
  • 4
  • 34
  • 44
0

Allow me to demonstrate a counterexample to your claim. You code seems to work correctly and the problem is elsewhere, most likely your Paragraph class.

By just changing the supporting framework (consisting of self and its content, page_data etc.) and the Paragraph class) I can demonstrate that your code (which I have used verbatim) works correctly, in that each element of self._elements is indeed different (most notably has a different id).

// [[[ MOCKED FRAMEWORK TO DEMONSTRATE THAT YOUR CODE WORKS
let self = { content: { page_data: [
  {type:'title'},
  {type:'paragraph'},
  {type:'paragraph'},
] } };
let nextUnusedId = 101;
let Paragraph = function () { this.element = { id: nextUnusedId++ } }
// ]]]

// Create Elements from Content
// The id's are created by UUIDV4 and are all different.
self._elements = new Array

let e;
self.content.page_data.forEach(cont => {
    switch (cont.type) {
        case 'paragraph':
            e = new Paragraph()
            console.log(e.element.id)
            self._elements.push(e)  
            break;

        case 'title':
            console.log('title')
        return 
    }
})
console.log(self._elements)
Wyck
  • 5,985
  • 4
  • 34
  • 44
  • could this be a problem due to the `Paragraph` being a class instead of a function? – HarrowXY Nov 11 '20 at 15:03
  • Why don't you post the Paragraph code and we'll see? But I could have easily made a class instead of a function here and still demonstrate it working correctly: Feel free to substitute `class Paragraph { constructor() { this.element = { id: nextUnusedId++ } } }` My counterexample stands (the element ids will still be different.) – Wyck Nov 11 '20 at 15:06
  • edited original, sorry for the bad formatting, this is my first question – HarrowXY Nov 11 '20 at 15:14
-1

Try just using a new variable declared inside the scope of the loop

// Create Elements from Content
// The id's are created by UUIDV4 and are all different.
self._elements = new Array

self.content.page_data.forEach(cont => {
    switch (cont.type) {
        case 'paragraph':
            var e = new Paragraph()
            console.log(e.element.id)
            self._elements.push(e)  
            break;

        case 'title':
            console.log('title')
        return 
    }
})
console.log(self._elements)

From your problem description, it sounds as if there is a single "reference" variable of 'e' and you are just creating an array of that reference over and over again, and whatever the loop last iterated over is what all those references point to

bkwdesign
  • 1,266
  • 19
  • 42