I have a parent component ChangeInfo, inside it is a child component ShowWorkInfo. Inside the ShowWorkInfo component, I have several input forms to update the job information. I created a variable work_info which is an object and then used the v-model for the fields inside. But I don't know how to make the parent component get data from the child component. I don't have any button inside the child component, I'll try to handle the data from WorkInfo with a button in the parent. This is my code. Should I write directly into ChangeInfo without splitting it into a child component
ChangeInfo (parent component)
export default class ChangeInfo extends Vue {
public isUpdated: boolean = false
updateWorkInfo(workInfo: any) {
if (
workInfo.company == '' ||
workInfo.department == '' ||
workInfo.position == '' ||
workInfo.postcode == '' ||
workInfo.prefectures == '' ||
workInfo.municipality == '' ||
workInfo.address == '' ||
workInfo.building == '' ||
workInfo.phone_number == '' ||
workInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/work_info/1', {
status: workInfo.status,
company: workInfo.company,
department: workInfo.department,
position: workInfo.position,
postcode: workInfo.postcode,
prefectures: workInfo.prefectures,
municipality: workInfo.municipality,
address: workInfo.address,
building: workInfo.building,
phone_number: workInfo.phone_number,
url: workInfo.url
})
.then(response => {
workInfo = response.data
console.log(workInfo)
InformationModule.CHANGE_WORK_INFO(workInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
workInfo.status = false
workInfo.company = ''
workInfo.department = ''
workInfo.position = ''
workInfo.postcode = ''
workInfo.prefectures = ''
workInfo.municipality = ''
workInfo.address = ''
workInfo.building = ''
workInfo.phone_number = ''
workInfo.url = ''
}
}
updatePersonalInfo(personalInfo: any) {
if (
personalInfo.nearest_station == '' ||
personalInfo.postcode == '' ||
personalInfo.prefectures == '' ||
personalInfo.municipality == '' ||
personalInfo.address == '' ||
personalInfo.building == '' ||
personalInfo.phone_number == '' ||
personalInfo.url == ''
) {
alert('完全な情報を入力してください')
this.isUpdated = false
} else {
axios
.put('https://609b82962b549f00176e394f.mockapi.io/personal_info/1', {
gender: personalInfo.gender,
nearest_station: personalInfo.nearest_station,
postcode: personalInfo.postcode,
prefectures: personalInfo.prefectures,
municipality: personalInfo.municipality,
address: personalInfo.address,
building: personalInfo.building,
phone_number: personalInfo.phone_number,
url: personalInfo.url
})
.then(response => {
personalInfo = response.data
console.log(personalInfo)
InformationModule.CHANGE_PERSONAL_INFO(personalInfo)
})
.catch(error => console.log(error))
this.isUpdated = false
personalInfo.gender = false
personalInfo.nearest_station
personalInfo.postcode = ''
personalInfo.prefectures = ''
personalInfo.municipality = ''
personalInfo.address = ''
personalInfo.building = ''
personalInfo.phone_number = ''
personalInfo.url = ''
}
}
triggerSubmit() {
this.isUpdated = true
}
I call two functions like this
<template>
<div class="d-block">
<ShowProfile />
<ShowWorkInfo :isUpdated="isUpdated" @update-work-info="updateWorkInfo" />
<ShowPersonalInfo
:isUpdated="isUpdated"
@update-personal-info="updatePersonalInfo"
/>
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="triggerSubmit"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
<ModalUpdateSuccess />
</div>
</template>
Well... there are multiple ways to do this:
common.btn.btn_update
is pressed, in the updateWorkInfo
function, you set up a watcher in the child component for this prop, and when this pro changes to true, you do an emit('submitted', data)
and this will emit the data to your parent component and then just handle this event in the parent as a submit event. In action://#region Parent script
import {
Component,
Vue
} from 'vue-property-decorator'
import ShowWorkInfo from './Components/ShowWorkInfo.vue'
import ModalUpdateSuccess from '@/components/Modal/ModalUpdateSuccess.vue'
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
private isFormSubmitted: boolean = false;
private validationMessage: string = '';
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
const { isFormValid, validationMessage } = await validateForm(workInfo);// function that validates your data, and returns a message and a boolean.
if(!isFormValid) { //if form is not valid, you have to set the variable that triggers
//the submit to false so the child component can set it to true and trigger submit once again
this.isFormSubmitted = false;
this.validationMessage = validationMessage;
return;
}
//...data handling logic and stuff... you can make the PUT request here, or anuy other data related action
}
triggerSubmit() {
//this triggers the watch in the child component
this.isFormSubmitted = true;
}
}
//# endRegion Parent script
//# region Child script
@Component({
components: {
Title
}
//the prop
props: {
isFormSubmitted: {
default: false,
type: boolean,
},
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ...
}
//watch for change (you can also put it in a computed if it does not trigger change)
watch: {
isFormSubmitted: function(newValue) {
if (newValue) {
console.log('form-submitted', this.workInfo)
emit('form-submitted', this.workInfo);
}
}
}
}
//#endRegion Child script
Now I don't really like this approach... but it works, just how you wanted it to!
#region Parent script
@Component({
components: {
ShowWorkInfo,
ModalUpdateSuccess
}
})
export default class ChangeInfo extends Vue {
updateWorkInfo(workInfo) {
console.log('recieved workinfo: ', workInfo);
//...data handling logic and stuf...
}
}
ShowWorkInfo (child component)
#endRegion Parent script
#region Child script
@Component({
components: {
Title
}
})
export default class ShowWorkInfo extends Vue {
private showWorkInfo: boolean = false
private workInfo: any = { ... }
//watch for change (you can also put it in a computed if it does not trigger change)
submitForm() {
console.log('submit form: ', this.workInfo);
//you could also validate the form at this point and dont emit unti the data is valid
this.$emit('form-submitted', this.workInfo);
}
}
#endRegion Child script
<!-- parent template -->
<template>
<div class="d-block">
<ShowWorkInfo @form-submitted="updateWorkInfo"/>
<ModalUpdateSuccess />
</div>
</template>
<!-- parent template end -->
<!-- child template -->
<template>
<div class="form">
<!-- your form fields -->
<div class="w--27 mw-100 mx-auto my-9">
<button
@click="submitForm"
v-b-modal="'update-success'"
class="btn btn-primary w-100"
>
{{ $t('common.btn.btn_update') }}
</button>
</div>
</div>
</template>
<!-- child template end -->
NOTE1: Apologies if I misused these variables and the this, since i am not familiar with this version of Vue and typescript, and tbh i have not touched vue.2 in like a year, but the concepts remain the same, essentially i just wanted to show you the methods of how to use the features vue gives, the above code is far from perfect but i think it illustrates the uses and answers you question.
NOTE2: There are more ways to do this, if you are interested in them please tell me. The above-mentioned two ways are the most common I have seen
UPDATE: Form validation in the first block. Try it, this is an overall form validation. DISCLAIMER: If you want to do field by field validation, that would be real hard, and would advise you to move the submit logic to your child component.