I am facing an issue with a Class
that has a proxy-based object. The set()
method modifies another property of the same class, and everything runs smoothly when the code is executed in JS/TS.
class Form {
errors = []
values = {}
constructor(values) {
this.values = new Proxy(values, {
set: (target, prop, value) => {
target[prop] = value
this.errors.push('test')
return true
},
})
}
}
const form = new Form({
name: 'Jhon',
age: 20,
})
form.values.name = 'Maria'
form.values.age = 30
console.log(form.errors)
My goal is to have the expected result for form.errors
, which should be an Array like ['test', 'test']
However, when I use Vue and include {{ form.errors }}
in the <template>
, it does not react as expected. It doesn't update in real-time.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<script src="https://unpkg.com/vue@3"></script>
<div id="app">{{ form.errors }}</div>
<script>
class Form {
errors = []
values = {}
constructor(values) {
this.values = new Proxy(values, {
set: (target, prop, value) => {
target[prop] = value
this.errors.push('test')
return true
},
})
}
}
const app = Vue.createApp({
data() {
return {
form: new Form({
name: 'Jhon',
age: 20,
}),
}
},
mounted() {
this.form.values.name = 'Maria'
this.form.values.age = 30
},
})
app.mount('#app')
</script>
</body>
</html>
form.errors
gets updated, but Vue fails to observe these changes accurately. This can be verified by adding:
mounted() {
this.form.values.name = 'Maria'
this.form.values.age = 30
this.form.errors.push('hello')
}
This will give the expected output on the DOM:
['test', 'test', 'hello']
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<script src="https://unpkg.com/vue@3"></script>
<div id="app">{{ form.errors }}</div>
<script>
class Form {
errors = []
values = {}
constructor(values) {
this.values = new Proxy(values, {
set: (target, prop, value) => {
target[prop] = value
this.errors.push('test')
return true
},
})
}
}
const app = Vue.createApp({
data() {
return {
form: new Form({
name: 'Jhon',
age: 20,
}),
}
},
mounted() {
this.form.values.name = 'Maria'
this.form.values.age = 30
this.form.errors.push('okay')
},
})
app.mount('#app')
</script>
</body>
</html>
I am looking for a solution where form.errors
becomes reactive in Vue just like any other property.