0

I am trying to make an array of objects from user input.

The object is pushed in array, but on the next step input overrides every object in array.

I have tried passing category.value and it works perfectly, but i want to pass the whole category.

for example:

  1. choose A, submit, output - "a" (as expected)
  2. choose B, submit, output - "b","b" (expected "a","b")

Why is it happening?

let form = document.getElementById('form');

let category = form.category;

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C(category);

    arr.push(c);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>
gmaziashvili
  • 250
  • 1
  • 19

2 Answers2

1

in your code let category is a direct reference to your select HTML element (and not a Javascript object). This reference is pushed into the array. each time you ask for the value, you directly get the value attribute from your select.. so it gets updated each time.

If you want a Javascript object with the value, you have to construct one and give it to your class:

let form = document.getElementById('form');

let category = form.category;

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C({ value: category.value });

    arr.push(c);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>

Note that it works because strings in Javascript are passed by value, and object by reference (value of the reference actually). If you had a global category object that you updated the value and pushed into the array, you would have the same problem:

let form = document.getElementById('form');

let category = form.category;

let categoryObj = { value: null };

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();
    
    categoryObj.value = category.value;
    let c = new C(categoryObj);

    arr.push(c);
    
    console.log('same problem you had because all items in the array are the same reference to the global object!');
    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>
Kaddath
  • 5,933
  • 1
  • 9
  • 23
0

The category object is the same object throughout your program, the user input is just changing it. When you populate an array with objects, they are in fact stored by reference, so what is happening in your code is your array is being populated by the same object. This is why you experience the duplication you described.

If instead, you did e.g. like this:

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C(category);

    arr.push(c.category.value);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i]);
    }
});

then the array is populated by the actual values and you would obtain the result you expect. If you want to store the C instances specifically, you could solve this by e.g. cloning the objects before pushing into the array.

Berthur
  • 4,300
  • 2
  • 14
  • 28