1

Is it possible, when I fire updateCountry method (defined in country-list component), to update the value (if successful call) of that array element, so that the button will dynamically change text based on country.show value?

This is the Vue code I have at the moment:

Vue.component('country-list', {
    template: `
    <tbody>
        <tr is="country" v-for="(country, index) in countries.data">
            <td>
                <input
                    type="text"
                    name="name"
                    class="form-control country-name"
                    :value="country.name"
                 >
            </td>
            <td>
                <select name="show" class="form-control country-show" :value="country.show">
                    <option value="0">No</option>
                    <option value="1">Yes</option>
                </select>
            </td>
            <td>
                <input
                    type="text"
                    name="order"
                    class="form-control country-order"
                    :value="country.order"
                 >
             </td>
            <td>
                <button class="btn btn-primary">
                    {{ country.show ? "Hide" : "Show" }}
                </button>
                <button class="btn btn-success"
                    @click="updateCountry"
                    :data-id="country.id">Update</button>
            </td>
        </tr>
    </tbody>
    `,

    props: ['countries'],

    methods: {

        updateCountry(event) {

            let self         = this;

            let countryID    = event.target.dataset.id;

            let parent       = event.target.closest('.parent');

            let countryName  = parent.getElementsByClassName('country-name')[0].value;

            let countryOrder = parent.getElementsByClassName('country-order')[0].value;

            let countryShow  = parent.getElementsByClassName('country-show')[0].value;

            axios.post('/country/insert', {
                id: countryID,
                name: countryName,
                order: countryOrder,
                show: countryShow
            })
            .then(function (response) {
                console.log(self);
            })
            .catch(function (error) {
                console.log(error);
            });

        }

    }
});

Vue.component('country', {
    template: `<tr class=parent><slot></slot></tr>`
});


Vue.component('pagination-list', {

    template: `
        <tfoot>
            <tr align="center">
                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li :class="countries.current_page == 1 ? 'disabled' : ''">
                            <a
                                :class="countries.current_page == 1 ? 'disabled' : ''"
                                :href="countries.current_page == 1 ? '#' : countries.prev_page_url"
                                @click.prevent="pagination(countries.current_page - 1)"
                                aria-label="Previous">
                                <span aria-hidden="true">&laquo;</span>
                            </a>
                        </li>

                        <li v-for="i in countries.last_page"
                        :class="countries.current_page == i ? 'active' : ''"
                        >
                            <a
                                :href="countries.current_page == i ? '#' : '/admin/countries?page='+i"
                                @click.prevent="pagination(i)"
                            >{{i}}</a>
                        </li>

                        <li>
                            <a
                                :href="countries.next_page_url"
                                @click.prevent="pagination(countries.current_page + 1)"
                                aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </tr>
        </tfoot>
    `,

    props: ['countries'],

    methods: {
        pagination(page) {
            this.$parent.getCountries(page);
        }
    }
});


let App = new Vue({

    el: '#app-container',

    data: {
        countries: []
    },

    created() {
        this.getCountries()
    },

    methods: {

        getCountries(page) {

            let self = this;

            let getParam = page ? '?page=' + page : '';

            axios.get('/admin/countries' + getParam)
                .then(function (response) {
                    self.countries  = response.data;
                })
                .catch(function (error) {
                    console.log(error);
                });

        },

        filterCountries(event) {

            let name = event.target.value;

            let self = this;

            if(name.length > 2) {

                axios.get('/country/search', {
                    params: {
                        name: name
                    }
                })
                .then(function (response) {
                    self.countries = response.data;

                    console.log(self.countries);
                })
                .catch(function (error) {
                    console.log(error);
                });

            }

            if((event.keyCode === 8 && name.length === 2) || !name.length){
                this.getCountries();
            }
        }
    }

})
2
  • Do you mean to update the country.show value? Commented Jun 20, 2017 at 19:19
  • Either that or the whole countries array, or just the array element which was used to update. Anything that will change text of the button from hide to show, or vice versa. Commented Jun 20, 2017 at 19:26

1 Answer 1

1

This code would be much more Vue like if you used v-model and it would cut down on some of the things you are having to do. For example if you update your country-list template like this:

<tbody>
    <tr is="country" v-for="(country, index) in countries.data" :key="country">
        <td>
            <input
                type="text"
                name="name"
                class="form-control country-name"
                v-model="country.name"
             >
        </td>
        <td>
            <select name="show" class="form-control country-show" v-model="country.show">
                <option value="0">No</option>
                <option value="1">Yes</option>
            </select>
        </td>
        <td>
            <input
                type="text"
                name="order"
                class="form-control country-order"
                v-model="country.order"
             >
         </td>
        <td>
            <button class="btn btn-primary">
                {{ country.show ? "Hide" : "Show" }}
            </button>
            <button class="btn btn-success"
                @click="updateCountry(country)"
                :data-id="country.id">Update</button>
        </td>
    </tr>
</tbody>

Then your updateCountry method could just be this

updateCountry(country) {
  axios.post('/country/insert', country)
    .catch(err => //do something on error)
}

Because using v-model, all the values are already updated locally, and you are just posting the values to the server. Since you are passing the actual country to the updateCountry method, there is no need to get the values from the inputs.

Note also, I added :key="country" to your v-for because a key is required when you iterate a component. If you have a country.id that would be even better as the key. But, again, I don't understand why you need the country component at all. It's completely unnecessary at this point.

Sign up to request clarification or add additional context in comments.

2 Comments

I am new to the Vue (started using it few days ago, still learning mind set behind it (Jquery is my go to js library for many years now, and Vue is nothing like Jquery)). Thanks a lot for helping me today :). It was a long day, and your help made it a bit easier :)
@Sasha You'll pick it up :) Vue makes a lot of things easier for you. Happy to help.

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.