1

I'm doing a site that uses laravel and vue js. The error I'm getting is this

[Vue warn]: 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: "selected_parent"

and this

[Vue warn]: Error in v-on handler (Promise/async): "Error: Request failed with status code 404"

I can't see where I'm going wrong.

Here is my product.blade.php

@extends('layouts.public')
@section('content')
    <div class="content_wrapper">
        @foreach($single_product as $product)
            <div class="row single_product_wrapper">
                <div class="col-lg-8 col-md-12-col-sm-12 product_details">
                    @foreach($parent_product as $parent)
                        <h1>
                            {{ $parent->title }}
                        </h1>

                        <table style="width: 100%; height: 95px;" border="2" cellspacing="5" cellpadding="5">
                            <tbody>
                                <tr style="text-align: center;">
                                    <td>
                                        <strong>Code</strong>
                                    </td>

                                    <td>
                                        <strong>Description</strong>
                                    </td>

                                    <td>
                                        <strong>Price</strong>
                                    </td>
                                </tr>

                                <tr style="text-align: center;">
                                    <td>
                                        {{ $parent->code }}
                                    </td>

                                    <td>
                                        {{ $parent->description }}
                                    </td>

                                    <td>
                                        {{ $parent->price }}
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    @endforeach

                    <!-- BEGIN ADD TO CART FORM -->
                    <div id="app">
                        @foreach($parent_product as $parent)
                            <code-selection :products="{{ $parent_product }}" :children="{{ $parent->parent }}"></code-selection>
                        @endforeach
                    </div>
                    <!-- END ADD TO CART FORM -->
                </div>
            </div>
        @endforeach
    </div>
@stop

and this is my vue

<template>
    <div>
        <form @submit.prevent="submit">
            <div class="row">
                <div class="col-lg-12 code_select">
                    <select name="code" id="code" class="form-control mb-2 mt-10" v-model="selected_parent" required>
                        <option :value="selected_parent">Please select your code</option>
                        <option v-for="product in products" :value="product.id">
                            {{ product.code }}
                        </option>

                        <option v-for="child in children" :value="child.id">
                            {{ child.code }}
                        </option>
                    </select>
                </div>
            </div>

            <input type="submit" class="btn btn-dark btn-lg btn-block" value="Add To Cart">
        </form>
    </div>
</template>

<script>
    import axios from 'axios'

    export default {
        props: [
            'products',
            'children',
            'selected_parent'
        ],

        mounted() {
            console.log('Component mounted.')
        },

        methods: {
            submit(){
                var formData = new FormData();

                formData.append('code', this.selected_parent);

                return axios.post('/add-to-cart/'+this.selected_parent, formData)
                            .then(
                                function(response)
                                {
                                     console.log(response.data.redirect);
                                     window.location = response.data.redirect;
                                }
                            );
            },
        },
    }
</script>

So what I would like to happen is, when the user selects a code and hits the Add To Cart button they will then get taken to the cart page, but right now that isn't happening when I select the code and hit the button nothing happens and I get the errors that I said in my console.

If there is anything else you need to know please let me know

Isis
  • 189
  • 4
  • 16
  • 1
    The first warning has been asked about many times before, e.g. https://stackoverflow.com/questions/40574661/avoid-mutating-a-prop-directly-since-the-value-will-be-overwritten/43828751. For the second warning you need to use the **Network** section of your browser's developer tools to figure out which request is returning the 404. That should allow you to establish whether the problem is with the UI or the server. If you need further help you should add the relevant request information to the question. – skirtle Jul 24 '19 at 08:35

1 Answers1

3

The answer is simple, you should break the direct prop mutation by assigning the value to some local component variables(could be data property, computed with getters, setters, or watchers).

Here's a simple solution using the watcher.

<template>
  <input
    v-model="input"
    @input="updateInput" />
</template>

<script>
  export default {
  props: {
    value: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      input: '',
    };
  },
  watch: {
    value: {
      handler(after) {
        this.input = after;
      },
      immediate: true,
    },
  },
  methods: {
    updateInput() {
      this.$emit('input', this.input);
    },
  },
};
</script>

It's what I use to create any data input components and it works just fine. Any new variables sent by parent v-model will be watched and assigned to the input variable and once the input is received, catch that action and emit input to parent suggesting that data is input from the form element.

And for the second part, when you receive the new url from redirect, simply replace the location href like this:

return axios.post('/add-to-cart/'+this.selected_parent, formData)
  .then((response) => {
    window.location.href = response.data.redirect;
  })
  .catch((error) => {
    console.log(error);
  })
);
Vectrobyte
  • 1,408
  • 12
  • 30