0
votes

I use Laravel and Vue. I have two components: parent and child.

Parent:

<template>
    <div>
        <sport-sites-add :applications-all-list="applicationsAll"></sport-sites-add>

        <table class="table">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Application id</th>
                <th scope="col">Name</th>
                <th scope="col">Description</th>
                <th scope="col">Picture</th>
                <th scope="col">URL</th>
                <th scope="col"></th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="sportSite in sportSites">
                <th scope="row">{{ sportSite.id }}</th>
                <td>
                    <template v-for="application in sportSite.applications">
                        id {{ application.id }} => {{ application.name }} <br>
                    </template>

                </td>
                <td>{{ sportSite.name }}</td>
                <td>{{ sportSite.description }}</td>
                <td>
                    <img style="width: 100px; height: 100px;" :src="sportSite.image" >
                </td>
                <td>
                    <a :href="sportSite.url" target="_blank">{{ sportSite.url }}</a>
                </td>
                <td>

                </td>
            </tr>

            </tbody>
        </table>
    </div>
</template>

<script>
    import { EventBus } from '../../app';

    export default {
        name: "SportSitesTable",
        mounted(){
            this.loadTable();
            this.getApplications();
        },
        methods:{
            loadTable: function () {
                window.axios.get('/sport_sites_all')
                    .then(resp => {
                        this.sportSites = resp.data.data;
                    }).catch(err => {

                    console.error(err);
                });
            },
            getApplications: function () {
                window.axios.get('/applications/all')
                    .then(resp => {
                        this.applicationsAll = resp.data.applications.data;
                    }).catch(err => {
                    console.error(err);
                });
            }
        },
        data(){
            return {
                sportSites: [],
                applicationsAll: [],
            }
        },
    }
</script>

Child:

<template>
    <div>
        <button type="button" class="btn btn-primary my-2" data-toggle="modal" data-target="#sportSiteAdd">
            Add
        </button>

        <div class="modal fade" id="sportSiteAdd" tabindex="-1" role="dialog" aria-labelledby="sportSiteAddLabel" aria-hidden="true">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="sportSiteAddLabel">Add sport site</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">

                        <ul class="alert-danger">
                            <li v-for="error in errors">
                                {{ error[0] }}
                            </li>
                        </ul>

                        <form>
                            <div class="form-group">
                                <label for="name">Title</label>
                                <input type="text" class="form-control" id="name" name="name" v-model="formFields.name">
                            </div>

                            <div class="form-group">
                                <label for="image">Picture</label>
                                <input type="text" class="form-control" id="image" name="image" v-model="formFields.image">
                            </div>

                            <div class="form-group">
                                <label for="url">URL</label>
                                <input type="text" class="form-control" id="url" name="url" v-model="formFields.url">
                            </div>

                            <div class="form-group">
                                <label for="description">Description</label>
                                <textarea class="form-control" id="description" name="description" v-model="formFields.description"></textarea>
                            </div>

                            <div>
                                <label class="typo__label">Applications </label>
                                <multiselect v-model="formFields.applications"
                                             tag-placeholder="Applications"
                                             placeholder="Search"
                                             label="name"
                                             track-by="id"
                                             :options="applications"
                                             :multiple="true"
                                             :taggable="true">
                                </multiselect>
                            </div>

                        </form>

                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary" v-on:click="submit">Save</button>
                    </div>
                </div>
            </div>
        </div>

    </div>
</template>

<script>
    import { EventBus } from '../../app';
    import Multiselect from 'vue-multiselect'

    export default {
        name: "SportSitesAdd",
        props: ['applicationsAllList'],
        methods:{
            submit: function (e) {
                window.axios.post('/sport_site/add/', this.formFields)
                    .then(res => {
                        console.log('Saved!');
                        $('#sportSiteAdd').modal('hide');

                        this.formFields.name = '';
                        this.formFields.image = '';
                        this.formFields.url = '';
                        this.formFields.description = '';

                        EventBus.$emit('reloadApplicationsTable');
                    }).catch(err => {
                    if(err.response.status === 422){
                        this.errors = err.response.data.errors || [];
                    }
                    console.error('Error of saving!');
                });
            },

        },
        data(){
            return {
                formFields: {
                    name: '',
                    image: '',
                    url: '',
                    description: '',
                    applications: this.applicationsAllList,

                },
                errors: [], 
            }
        },
        components: {
            Multiselect
        },
    }

</script>

The parent component is a table. Child component is a form for the table. I pass a data from the parent to the child via props:

<sport-sites-add :applications-all-list="applicationsAll"></sport-sites-add>

In the child component I have a plugin for creating a multiple select. The plugin requires 'options' and 'values' collections. It's very simple, documentation with my case is here https://vue-multiselect.js.org/#sub-tagging. At the result I want to see the following: all items on the select are selected. But I have just the empty collection during mounting of the child component. I have available items on the 'select' but I dont know how I can make it selected by default. Obviously, I need to copy the applicationsAllList into local data() of child component and use it. But it not available during mounted and beforeMounted. console.log tells me that the child is faster.

enter image description here

1

1 Answers

1
votes

you're missing @tag function & v-model, in this case, must be array, You need to use applicationsAllList props directly on options

                            <multiselect v-model="formFields.value"
                                         tag-placeholder="Applications"
                                         placeholder="Search"
                                         label="name"
                                         track-by="id"
                                         :options="applicationsAllList"
                                         :multiple="true"
                                          @tag="addTag"
                                         :taggable="true">
                            </multiselect>

in methods add addTag function and add value as array

  data() {
    return {
      formFields: {
        name: '',
        value: [],
        image: '',
        url: '',
        description: '',
      },
      errors: [],
    }
  },
  methods: {
    addTag (newTag) {
      const tag = {
        name: newTag,
        code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
      }
      this.options.push(tag)
      this.value.push(tag)
    }
  }