简体   繁体   中英

Vue.js Pass just created data from child to parent component

I have a Vue.js/Laravel application in which i am struggling with a simple task. I have a child component called Create, which creates a new item into the DB and supposedly should emit this new created data to a parent component, so that i would include this new created data into a array on the parent component called jobs. That doesnt actually work and i have to refresh the page in order to see that on the parent component. Can anyone help me on that?

This is my child component Create.vue

<template>
  <div class="modal-backdrop">
    <div class="modal">
      <header class="modal-header">
        <slot name="header">
          <h3>Create new position</h3>
          <button type="button" class="btn-close" @click="close">
            x
          </button>
        </slot>
      </header>
      <section class="modal-body">
        <slot name="body">
                    <label for="title">Title</label>
                    <input v-model="job.name" type="text" name="name" class="form-control" required>

                    <label for="salary">Salary / Amount (k) per year (eg.:30, 40, 65)</label>
                    <input v-model="job.salary" type="number" name="salary"  class="form-control">

                    <label for="location">Location</label>
                    <input v-model="job.location" type="text" name="location" class="form-control" required>

                    <label for="experience">Years of experience eg.:1,2,4,5</label>
                    <input v-model="job.experience_years" type="number" name="experience_years" class="form-control" required>

                    <label for="benefits">Bonus - Benefits</label>
                    <input v-model="job.bonus" type="text" name="bonus" class="form-control">

                    <label for="description">Description / Job details</label>
                    <textarea v-model="job.description" rows="4" cols="50" name="description" class="form-control large"></textarea>
                    <br>

                    <input @click="saveJob" type="button" class="btn btn-primary" value="Save">
        </slot>
      </section>
      <footer class="modal-footer">
    </footer>
  </div>
</div>
</template>

<script>
 import moment from 'moment';
  export default {
    name: 'Create',

    data(){
        return{
            jobs: [],
            job: {id:'', name:'', description:'', salary:'', location:'', experience_years:'', bonus:'', expiration:'', created_at:''},
        }
    },

    methods:{

      close(job){
        this.$emit('newJob', job);
        this.$emit('closeCreateRequest');
      },

      moment,

      saveJob(){
          axios.post('http://localhost:8888/fintechjobs.io/public/api/job/createJob',this.job).then((response) => {
              this.close(this.job);
        }).catch((error) => this.errors = error.response.data.errors);

      }

    }
  }
</script>

<style>
  .modal-backdrop {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .modal {
    background: #FFFFFF;
    box-shadow: 2px 2px 20px 1px;
    overflow-x: auto;
    display: flex;
    flex-direction: column;
    left:25%;
    margin-left:15%px;
    position:fixed;
    width:50%;
    height: 70%;
    top:10%;
    overflow-y: auto;
    /* border: 1px black solid; */
  }

  .modal-header,
  .modal-footer {
    padding: 15px;
    display: flex;
    border: none!important;
  }

  .modal-header {
    /* border-bottom: 1px solid #eeeeee; */
    color: #214761;
    justify-content: space-between;
  }

  .modal-footer {
    /* border-top: 1px solid #eeeeee; */
    justify-content: flex-end;
  }

  .modal-body {
    position: relative;
    padding: 20px 20px;
    position: relative;
    padding: 20px 10px;
    margin-top: 30px;
    margin-left: 7px;
  }

  .btn-close {
    border: none;
    font-size: 20px;
    padding: 18px;
    cursor: pointer;
    font-weight: bold;
    color: #214761;
    background: transparent;
  }

  .btn-green {
    color: white;
    background: #4AAE9B;
    border: 1px solid #4AAE9B;
    border-radius: 2px;
  }


</style>

This is the parent component Vancancies.vue, which is supose to receive the data an insert into the jobs list:

<template>
    <div id="page-wrapper" >
    <div id="page-inner">
        <div class="row">
            <div class="col-lg-12">
                <h2>My job vacancies</h2>
                <!--  if(count($positions) > 0) { echo "";} else{ echo "No positions for the moment!"; -->

            <button v-if="this.company_remaining_jobs > 0" @click="openJobCreateModal" type="button" class="btn btn-primary modal-primary" data-toggle="modal" data-target="#exampleModalLong" >Create position</button>

                <table class="table table-bordered">
                    <thead>
                        <tr>
                            <th>Title</th>
                            <th>Created</th>
                            <th></th>
                        </tr>
                    </thead>
                     <tbody>
                         <tr v-for="job in jobs.jobs" :key="job.id" :job="job">
                            <td>{{job.name}}</td>
                            <td>{{moment(job.created_at).fromNow()}}</td>
                            <td style="text-align:center">
                                <button @click="openViewJobModal(job)" class="btn btn-large btn-success">View</button>
                                <button class="btn btn-large btn-primary">Edit</button>
                            </td>
                        </tr>
                    </tbody>
                </table>
        </div>
        <!-- endif -->
            </div>
        </div>
        <Show v-if="viewJobModalVisible" :job="job" @closeRequest='closeJobViewModal'></Show>
        <Create v-if="createJobModalVisible" @closeCreateRequest='closeJobCreateModal' @newJob='getNewJob'></Create>
    </div>
</template>

<script>

    import axios from 'axios';
    import moment from 'moment';
    import Show from './Show.vue';
    import Create from './Create.vue';

    export default {

        data(){

            return {
                jobs: [],
                job: {id:'', name:'', description:'', salary:'', location:'', experience_years:'', bonus:'', expiration:'', created_at:''},
                viewJobModalVisible: false,
                createJobModalVisible: false,
                company_remaining_jobs: '',
                newJob:''
            }

        },

        methods:{

            getJobs(){
                axios.get('http://localhost:8888/fintechjobs.io/public/api/vacancies').then( response => {
                    this.jobs = response.data
                }).catch(e => {
                    console.log(e);
                })
            },

            getCompanyInfo(){
                axios.get('http://localhost:8888/fintechjobs.io/public/api/company_info').then(response =>{
                    this.company_remaining_jobs = response.data.company_remaining_jobs;
                })
            },

            moment,

            openViewJobModal(job){
                this.job = job;
                this.viewJobModalVisible = true;
            },

            closeJobViewModal(){
                this.job = '';
                this.viewJobModalVisible = false;
            },

            openJobCreateModal(){
                this.createJobModalVisible = true;
            },

            closeJobCreateModal(){
                this.createJobModalVisible = false;
            },

            getNewJob(value){
                console.log(value);
                this.jobs.push(value)
            }
        },

        mounted(){
            this.getJobs();
            this.getCompanyInfo();
        },

        components:{
            Show,
            Create
        }


    }
</script>

Curiously this is how i can see the just created data on the console and the errors: 在此处输入图片说明 在此处输入图片说明

I think the problem is that your initial getJobs() call to populate jobs is overwriting the empty Array with an Object, and the .push() method does not work on Objects. Evidence of this can be seen where you reference jobs.jobs , as only an Object can have a named property:

// jobs must be an Object to have a named property
<tr v-for="job in jobs.jobs" :key="job.id" :job="job">

// ideally, this would be 
<tr v-for="job in jobs" :key="job.id" :job="job">

Assuming your existing jobs are currently populating properly, edit the getJobs() method by changing this line, along with the line above:

this.jobs = response.data;

// try changing to
this.jobs = response.data.jobs;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM