4

I'm stuck on a problem and was hoping that a Javascript Jedi could help point me in the right direction.

Scope of the problem:

I'm passing a Laravel collection to my Vue component. Inside the component, I'm iterating through the collection and submitting a form via axios. The form submits, the data is updated in the database, but __I'm not clear on how to show the updated value without a page refresh.__

Expected Outcome:

The updated data is reflected in the {{ collection.value }} inside the Vue template after form submission

What's going wrong:

The data is being updated in the database, but the {{ collection.value }} remains the same until page is reloaded.

Web.php:

Route::post('/updateQty', 'MyController@update');

MyController:

public function update(Request $request)
{
    $product = Product::where('id', $request->productId)
        ->update([ 'qty' => $request->qty ]);

    return response()->json($product);
}


public function index()
{

    $collection = DB::table('products')->get();

    return view('my-blade', [
        'collections' => $collection,
    ]);

}

Structure of $collection as stored in the database:

'qty' => decimal(8,2),
'class' => varchar(255),
'description' => varchar(255),
'value' => decimal(8,2),
'productId' => int(11)

my-blade:

<my-component :collections="{{ $collections }}"></my-component>

MyComponent.vue:

<template>
    <div class="container">
        <div class="row">
            <div class="col-lg-12">
                <table class="table table-sm">
                    <div v-if="collections.length">
                        <tr v-for="collection in collections" v-bind:key="collection.id">
                            <td>
                                <form @submit="updateQty">
                                <input type="hidden" id="productId" :value="collection.productId" name="productId">
                                    <select class="form-control" name="qty" id="qty" @change="updateQty">
                                        <option :value="collection.qty">{{ collection.qty }}</option>
                                        <option v-for="(x, index) in 200" v-bind:key="index" :value="index">{{ index }}</option> 
                                </select>
                                </form>
                            </td>
                            <td>{{ collection.value }}</td>
                        </tr>
                    </div>
                </table>
            </div>
        </div>
    </div>
</template>


<script>

export default {
    props: ['collections'],

    data() {
        return {
            qty: '',
        }
    }

    mounted() {
        console.log('MyComponent.vue mounted successfully');
    },

    methods: {

        updateQty(e) {
            e.preventDefault();

            let currentObj = this;
            let url = '/updateQty';

            axios.post(url, {
                qty: qty.value,
            })

            .then(function (response) {
                currentObj.value = (response.data);
                let collections = response.data;
            })
        },

    }
}
</script>

App.js

Vue.component('my-component', require('./components/MyComponent.vue'));

I'm sure it's something simple, but for the life of me I can't wrap my head around it. Thank you very much in advance!

1 Answer 1

4

You just need to change up your script a bit.

First, save the collections property to a data property, or Vue will scream when you try to update it. To do this, I would rename the incoming prop as something like collections_prop. Then save it to the collections data property.

Then change let collections = to this.collections = in your update response.

EDIT: I changed the .then function to ES6 syntax as you may have trouble accessing the this variable otherwise. No need for the currentObj stuff.

export default {
    props: ['collections_prop'],

    mounted() {
        console.log('MyComponent.vue mounted successfully');
    },
    data() {
        return {
            collections: this.collections_prop;
        }
    },
    methods: {

        updateQty(e) {
            e.preventDefault();

            let url = '/updateQty';

            // not sure where qty is coming from 
            // but you said that's all worked out
            // on your end

            axios.post(url, {
                qty: qty.value,
            })

            .then(response => {
                this.collections = response.data;
            })
        },

    }
}

And finally, don't forget to update the prop in your view.

<my-component :collections_prop="{{ $collections }}"></my-component>

Or if you want to later specify prop type as JSON:

<my-component :collections_prop='@json($collections)'></my-component>
Sign up to request clarification or add additional context in comments.

6 Comments

Hey @matticustard ! Thanks for helping me out with this. I really appreciate it! For clarity, the qty definitely submits and it updates the record in the database. I'll update my question with the contents of the $collections array, if that helps?
Interesting. How is it that you are accessing the qty variable in updateQty when it's never clearly defined? Can you point to the documentation for this feature? I'm just curious how it's done.
My apologies! I just tried to re-write this sample code from the actual and just left it out by accident. I have qty listed under data() - I'll update my answer. Not a feature, just a brain fart
Even so, I assume you'd have to use this.qty to access it. Anyway, if it's working then great. I won't bother you about it anymore.
Solved it! Thank you SO MUCH for helping me out. The missing link here was that I needed to return the $collections collection again in my update function. I really appreciate you taking the time today!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.