背景:
我正在从模态(具有子组件)内部添加新的actor数据,作为回报,无论何时子组件添加新的actor,父组件中的multiselect都应使用新添加的值进行更新。
代码:
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>
<!-- 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>
<!-- 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: </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>
<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的新手,我不知道我要去哪里错了,任何建议和提示都会有所帮助。
答案 0 :(得分:0)
第一=>要将数据从子级发送到父级: 脚本中使用的子组件
this.$emit('your-event-name',value)
并在父组件中使用:
<child-component
@your-event-name="event-handler"
/>
第二个=>将数据从父级发送到子级: 在父项中使用道具“:”
<child-component
:propName="value"
/>
在子组件中使用:
props: ["propName"]