0

背景:

我正在从模态(具有子组件)内部添加新的参与者数据,并且每当子组件添加新参与者时,父组件中的多选应该使用新添加的值进行更新。

代码:

Moviecreatecomponent.vue(父组件)

<template>
  <div class="container">
    <br />
    <!-- Dynamic alert tag for displaying success and failure messages -->
    <b-alert
      :show="dismissCountDown"
      dismissible
      :variant="alertVariant"
      @dismissed="dismissCountDown=0"
      @dismiss-count-down="countDownChanged"
    >{{alertMessage}}</b-alert>

    <div class="row">
      <!-- Actor modal button -->
      <b-button
        @click="actorModalShow = !actorModalShow"
        style="float:left"
        class="btn btn-info"
      >Add Actor</b-button>&nbsp;&nbsp;&nbsp;
      <!-- Actor modal -->
      <b-modal v-model="actorModalShow" title="Add Actor" hide-footer>
        <!-- common component for actor/producer (actor) -->
        <app-person-create
          @closeActorModal="closeActorModal"
          childtype="Actor"
          @alertFromChild="showAlert"
        />
      </b-modal>

      <!-- Producer modal button -->
      <b-button
        @click="producerModalShow = !producerModalShow"
        style="float:right"
        class="btn btn-info"
      >Add Producer</b-button>&nbsp;&nbsp;&nbsp;
      <!-- Producer modal-->
      <b-modal v-model="producerModalShow" title="Add Producer" hide-footer>
        <!-- common component for actor/producer (producer) -->
        <app-person-create
          @closeProducerModal="closeProducerModal"
          childtype="Producer"
          @alertFromChild="showAlert"
        />
      </b-modal>
    </div>
    <br />

    <!-- form component -->
    <form>
      <div class="row">
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6">
          <!-- Movie name -->
          <div class="form-group">
            <label for="moviename">Movie Name:</label>
            <input
              id="moviename"
              name="moviename"
              v-validate="'required'"
              data-vv-validate-on="validateStep"
              v-model="movieData.name"
              type="text"
              class="form-control"
            />
            <span class="error" v-show="errors.has('moviename')">{{ errors.first('moviename') }}</span>
          </div>
          <!--Year Of Release -->
          <div class="form-group">
            <label for="yearOfRelease">Year Of Release:</label>
            <input
              id="yearOfRelease"
              name="yearofrelease"
              v-model="movieData.yearOfRelease"
              type="date"
              class="form-control"
              v-validate="'required'"
              data-vv-validate-on="validateStep"
            />
            <span
              class="error"
              v-show="errors.has('yearofrelease')"
            >{{ errors.first('yearofrelease') }}</span>
          </div>
        </div>
      </div>
      <div class="row">
        <!-- Plot -->
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group">
          <label for="plot">Plot:</label>
          <br />

          <textarea
            id="plot"
            name="plot"
            v-validate="'required'"
            data-vv-validate-on="validateStep"
            v-model="movieData.plot"
            rows="5"
            class="form-control"
          />
          <span class="error" v-show="errors.has('plot')">{{ errors.first('plot') }}</span>
        </div>
      </div>
      <div class="row">
        <!-- Poster -->
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group">
          <label for="poster">Poster:</label>
          <br />
          <input
            id="poster"
            name="poster"
            v-model="movieData.poster"
            v-validate="'required'"
            data-vv-validate-on="validateStep"
            type="text"
            class="form-control"
          />
          <span class="error" v-show="errors.has('poster')">{{ errors.first('poster') }}</span>
        </div>
      </div>
      <div class="row">
        <!-- Actors -->
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group">
          <label for="actors">Actors:</label>
          <br />
          <multiselect
            v-model="movieData.actors"
            :options="actorNameDataFromJson"
            :multiple="true"
            label="name"
            track-by="id"
          />
        </div>
      </div>

      <hr />
      <div class="row">
        <!-- Producers -->
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group">
          <label for="actors">Producers:</label>

          <multiselect
            v-model="movieData.producers"
            :options="producerNameDataFromJson"
            :multiple="true"
            label="name"
            track-by="id"
          />
        </div>
      </div>
      <div class="row">
        <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
          <button class="btn btn-primary" @click.prevent="validateBeforeSubmit">Submit!</button>
        </div>
      </div>
    </form>
    <hr />
  </div>
</template>

<script>
import axios from "axios";
import PersonCreate from "../Person/PersonCreateComponent";

export default {
  components: {
    "app-person-create": PersonCreate
  },
  data: function() {
    return {
      //used to retrieve actor data for multiselect options
      actorNameDataFromJson: [],
      //used to retrieve producer data for multiselect options
      producerNameDataFromJson: [],
      //objects for alerts
      dismissSecs: 5,
      dismissCountDown: 0,
      alertVariant: "",
      alertMessage: "",
      //objects used for modals
      actorModalShow: false,
      producerModalShow: false,
      //objects used for all the inputs
      movieData: {
        id: 0,
        name: "",
        yearOfRelease: "",
        plot: "",
        poster: "",
        actors: [], //selected actors
        producers: [] //selected producers
      }
    };
  },
  created() {
    //data for the edit part
    console.log("Created");
    if (this.$route.params.id) {
      axios
        .get(`http://195.201.189.119:63790/movies/` + this.$route.params.id)
        .then(res => {
          this.movieData = res.data;
        });
    }

    this.loadActorMultiselect();
    this.loadProducerMultiselect();
  },

  methods: {
    // clears the form
    clearform() {
      this.movieData.id = null;
      this.movieData.name = null;
      this.movieData.yearOfRelease = null;
      this.movieData.plot = null;
      this.movieData.poster = null;
      this.movieData.actors = null;
      this.movieData.producers = null;
    },

    //form submit
    submited() {
      this.submitedform = true;
      let data = this.movieData;
      // checks if the id is equal to initial value
      if (this.moviedata.id == 0) {
        axios
          .post("http://195.201.189.119:63790/movies", this.moviedata)
          .then(res => {
            console.log(res.status);

            this.clearform();
          })
          .catch(error => {
            console.log(error);
            this.callDangerAlert();
          });
        this.callSuccessAlert();
      }
      //if not then it will update the data
      else {
        axios
          .put(
            `http://195.201.189.119:63790/movies/` + this.moviedata.id,
            this.moviedata
          )
          .then(res => {
            console.log(res.status);
            this.clearform();
          })
          .catch(error => {
            console.log(error);
            this.callDangerAlert();
          });
        this.callSuccessAlert();
      }
      console.log(data, "Final form submitted data");
    },

    //methods for alerts
    callSuccessAlert() {
      console.log("I am here success");
      this.childAlert.variant = "success";
      this.childAlert.message = "Data Recorded Successfully!!";
      this.$emit("alertFromChild", this.childAlert);
      console.log();
    },
    callDangerAlert() {
      this.childAlert.variant = "danger";
      this.childAlert.message = "Something Went Wrong!!";
      this.$emit("alertFromChild", this.childAlert);
    },
    // method to close producer modal from child button
    closeProducerModal() {
      this.producerModalShow = false;

      //reloads producer multiselect
      this.loadProducerMultiselect();
    },

    // method to close actor modal from child button
    closeActorModal() {
      this.actorModalShow = false;
      // reloads actor multiselect
      this.loadActorMultiselect();
    },

    //Loads actor multiselect
    async loadActorMultiselect() {
      //gets all actor names from actor json and formats it as {id:,name:}

      try {
        let response = await axios.get("http://195.201.189.119:63790/actors");
        let data = response.data;
        let actorNamesOption = [];

        for (let i = 0; i < data.length; i++) {
          if ((data[i].id && data[i].name) || data[i].personname) {
            actorNamesOption.push({
              id: data[i].id,
              name: data[i].name || data[i].personname
            });
          }
        }
        this.actorNameDataFromJson = actorNamesOption;
      } catch (error) {
        console.log(error);
      }
    },
    async loadProducerMultiselect() {
      //gets all producers names from producers json and formats it as {id:,name:}
        try {
        let response = await axios.get("http://195.201.189.119:63790/producers");
        let data = response.data;
        let producerNamesOption = [];
        for (let row in data) {
          if ((data[row].id && data[row].name) || data[row].personname) {
            producerNamesOption.push({
              id: data[row].id,
              name: data[row].name || data[row].personname
            });
          }
        }
        this.producerNameDataFromJson = producerNamesOption;
      } catch (error) {
        console.log(error);
      }
    },
    //setting countdown variables
    countDownChanged(dismissCountDown) {
      this.dismissCountDown = dismissCountDown;
    },
    //dynamic alert component for success and failure
    showAlert(alertDataFromchild) {
      this.alertVariant = alertDataFromchild.variant;
      this.alertMessage = alertDataFromchild.message;
      this.dismissCountDown = this.dismissSecs;
    },
    // validates for all the fields and calls submited method
    validateBeforeSubmit() {
      this.$validator.validateAll().then(result => {
        if (result) {
          this.submited();
          return;
        }
        alert("Please enter all the details!");
      });
    }
  }
};
</script>
  <style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
  <style>
.error {
  color: red;
}
.childbutton {
  float: right;
  margin-left: 5px;
}
</style>

Personcreatecomponent.vue(子组件)

<template>
  <div>
    <form @submit.prevent="validateBeforeSubmit">
      <div class="row">
        <div class="col-xs-12 col-sm-12">
          <div class="form-group">
            <label for="personname">{{childtype}} Name:</label>
            <input
              id="personname"
              v-model="personData.personname"
              type="text"
              name="personname"
              class="form-control"
              v-validate="'required|alpha'"
            >
            <span class="error" v-show="errors.has('personname')">{{ errors.first('personname') }}</span>
          </div>

          <div class="form-group">
            <label for="bio">{{childtype}}'s gender: &nbsp;</label>
            <label for="male">
              <input
                id="male"
                v-model="personData.sex"
                name="genderradiogroup"
                v-validate="'required|included:Male,Female'"
                type="radio"
                value="Male"
              > Male
            </label>
            &nbsp; &nbsp; &nbsp;
            <label for="female">
              <input
                id="female"
                v-model="personData.sex"
                name="genderradiogroup"
                type="radio"
                value="Female"
              > Female
            </label>
            <br>
            <span
              class="error"
              v-show="errors.has('genderradiogroup')"
            >{{ errors.first('genderradiogroup') }}</span>
          </div>

          <div class="form-group">
            <label for="bio">{{childtype}}'s bio:</label>
            <br>

            <textarea
              id="bio"
              name="bio"
              v-validate="'required|alpha'"
              v-model="personData.bio"
              rows="5"
              class="form-control"
            />
            <span class="error" v-show="errors.has('bio')">{{ errors.first('bio') }}</span>
          </div>

          <div class="form-group">
            <b-button variant="success" class="childbutton" @click="validateBeforeSubmit">Submit</b-button>
            <b-button variant="danger" class="childbutton" @click="closepersonmodal">Cancel</b-button>
          </div>
        </div>
      </div>
    </form>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data: function() {
    return {
      personData: {
        personname: "",
        sex: "",
        bio: ""
      },
      childAlert: {
        variant: "",
        message: ""
      }
    };
  },

  props: ["childtype"],
  methods: {
    //method used to get all fields that are entered in person modal
    personsubmited() {
      if (this.childtype == "Actor") {
        console.log(this.childtype);

        axios
          .post("http://195.201.189.119:63790/actors", this.personData)
          .then(res => {
            console.log(res.status);
          })
          .catch(error => {
            console.log(error);
            this.callDangerAlert();
          });
        this.callSuccessAlert();
      } else if (this.childtype == "Producer") {
        console.log(this.childtype);
        axios
          .post("http://195.201.189.119:63790/producers", this.personData)
          .then(res => {
            console.log(res.status);
          })
          .catch(error => {
            console.log(error);
            this.callDangerAlert();
          });
        this.callSuccessAlert();
      }

      this.$emit("close" + this.childtype + "Modal",this.personData);
    },
    validateBeforeSubmit() {
      this.$validator.validateAll().then(result => {
        if (result) {
          this.personsubmited();
          return;
        }
        alert("Please enter all the details!");
      });
    },
    callSuccessAlert() {
      console.log("I am here success");
      this.childAlert.variant = "success";
      this.childAlert.message = "Data Recorded Successfully!!";
      this.$emit("alertFromChild", this.childAlert);
      console.log();
    },
    callDangerAlert() {
      this.childAlert.variant = "danger";
      this.childAlert.message = "Something Went Wrong!!";
      this.$emit("alertFromChild", this.childAlert);
    },
    closepersonmodal() {
      this.$emit("close" + this.childtype + "Modal");
    }
  }
};
</script>

<style>
.error {
  color: red;
}
.childbutton {
  float: right;
  margin-left: 5px;
}
</style>

我是 vue 的新手,我不知道我哪里出错了,任何建议,提示都会有所帮助。

4

1 回答 1

0

首先 => 将数据从子组件发送到父组件:在脚本中使用子组件

this.$emit('your-event-name',value) 

并在父组件中使用:

<child-component
          @your-event-name="event-handler"
        />

第二 => 从父级向子级发送数据:在父级组件中使用道具“:”

<child-component
          :propName="value"
        />

在子组件中使用:

props: ["propName"]

于 2019-12-19T11:04:59.797 回答