E
E
Emptyform2019-08-12 11:38:01
Vue.js
Emptyform, 2019-08-12 11:38:01

How to get rid of the mutation error when passing a value to the component's edit field?

I pass the value that is output to the Input, and by clicking on the button I pass the contents of the input up to the parent.
Everything would be fine, but warnings about the mutation are pouring into the log:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "pname"

I tried to fasten computed, it did not help. Apparently I'm not doing it right.
Tell me what's wrong here, please:
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <script src="https://unpkg.com/vue"></script>
</head>

<body>

<div id="app">
    <todo-add
        v-on:todo-new="addNewTodo"
        :pname="newTodoName"
    ></todo-add>
    <p><pre>{{todosObj}}</pre></p>
</div>

<script>
    Vue.component('todo-add', {
        props: ['pname'],
        template:
        `<ul>
            <input v-model="todoName" autofocus></input>
            <button v-on:click="add">Add New Todo</button>
        </ul>`,
        computed: {
            todoName: {
                set: function(val) {
                    this.pname = val;
                },
                get: function() {
                    return this.pname.trim();
                }
            }
        },
        methods: {
            add: function() {
                console.log(`emit: this.name = ${this.pname}`);
                this.$emit('todo-new', this.todoName);
            }
        }
    });

    var app = new Vue({
        el: "#app",
        data: {
            newTodoName: '',
            todoArr: [
                {id: 1, name: "aaaaaa"},
            ]
        },
        methods: {
            addNewTodo: function(name) {
                let newItem = {id: this.todoArr.length+1, name: name}
                this.todoArr.push(newItem);
                this.newTodoName = ''; // чистим поле ввода
            }
        },
        computed: {
            todosObj: function() {
                return JSON.stringify(this.todoArr, null, 4);
            }
        }
    });
</script>

</body>
</html>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
0
0xD34F, 2019-08-12
@0xD34F Vue.js

Obviously, make pname a property of the component instead of a parameter.

<div id="app">
  <todo-add @todo-new="addNewTodo"></todo-add>
  <pre>{{ todoJson }}</pre>
</div>

Vue.component('todo-add', {
  template: `
<div>
  <input v-model="name" autofocus></input>
  <button @click="add">Add New Todo</button>
</div>`,
  data: () => ({
    name: '',
  }),
  methods: {
    add() {
      const name = this.name.trim();
      if (name) {
        this.$emit('todo-new', name);
        this.name = '';
      }
    },
  },
});

new Vue({
  el: '#app',
  data: {
    todoArr: [
      { id: 1, name: 'hello, world!!' },
    ],
  },
  methods: {
    addNewTodo(name) {
      this.todoArr.push({
        id: 1 + Math.max(0, ...this.todoArr.map(n => n.id)),
        name,
      });
    },
  },
  computed: {
    todoJson() {
      return JSON.stringify(this.todoArr, null, 2);
    },
  },
});

S
s_lukinin, 2019-08-12
@s_lukinin

Create a component property with parameter value https://vuejs.org/v2/guide/components-props.html#O...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question