hotwired / stimulus

A modest JavaScript framework for the HTML you already have
https://stimulus.hotwired.dev/
MIT License
12.73k stars 426 forks source link

Controller object and array values can't be modified unless default value is provided #707

Closed christophehenry closed 1 year ago

christophehenry commented 1 year ago

Hi! I just stumbled upon a very strange behavior of values: objects and array values can't be modified unless a default value is provided.

Here is a simple example:

class TestController extends Stimulus.Controller {
    connect () {
        this.arrValue.push("Test");
        this.arrDefValue.push("Test");
        this.objValue["test"] = "test";
        this.objDefValue["test"] = "test";

        console.log(this.arrValue);
        console.log(this.arrDefValue);
        console.log(this.objValue);
        console.log(this.objDefValue);
    }

    static values = {
        arr: Array,
        arrDef: {type: Array, default: []},
        obj: Object,
        objDef: {type: Object, default: {}}
    }
}

This will print:

Array []
Array [ "Test" ]
Object {  }
Object { test: "test" }

Maybe this is expected but this is not what's documented.

lb- commented 1 year ago

Very similar to this previous question. https://github.com/hotwired/stimulus/issues/593

This way of modifying values is not the documented approach. Instead of thinking of the fooValue as an instance value, remember they are a getter and setter pair.

When retrieving someValue, it is reading from the DOM, when you set it by using this.someValue = ['new']; you are writing the DOM. There are no instance values being mutated.

You are best to avoid confusion by writing to the array as per the documentation.

const arrValue = this.arrValue; // reminder. Will error if no value set in the DOM, intentionally. 
arrValue.push('test');
this.arrValue = arrValu;

This should work as expected. Here you are first getting the value, then mutating it, finally setting it back.

christophehenry commented 1 year ago

Maybe I missed something but this snippet is not in the documentation, is it?

lb- commented 1 year ago

Maybe it could be clearer in the docs but it does state that the fooValue methods are getters and setters.

https://stimulus.hotwired.dev/reference/values#properties-and-attributes

christophehenry commented 1 year ago

Ok, thank you. Closing, then.