Reputation: 2953
Using $emit
for communicating between child
to parent
component. I have a method in child component which trigger the $emit during diffferent stages of an api
call. ie, before doing the api call I need to send few values to parent to disable some fields in parent. So using $emit
to sent those values and it works successfully. But then when I try to call same $emit event after getting the result from api in same method it is not getting updated. The values are successfully getting emitted from child but in parent it only updates the first time.
Here is the parent component
<template>
<div>
<div class="horizontal-fields">
<input
id="General_mobile"
class="input-fied"
name="mobileNumber"
placeholder="Enter your mobile"
type="number"
autocomplete="new mobile"
:disabled="otpInput.isVerifying"
>
<input @click.prevent="sendVerificationCode" value="sendotp" class="otp-btn" type="button">
</div>
<div v-if="otpInput.isOtpMode">
<GeneralOtp
:message="otpGeneratedMessage"
:mobileNumber="this.mobileNumber"
@handleComplete="handleCompleteOtp"
/>
</div>
</div>
</template>
<script>
import axios from "axios";
import GeneralOtp from "./GeneralOtp";
export default {
name: "MobileVerification",
components: {
GeneralOtp
},
data() {
return {
mobileNumber: null,
isValidMobile: null,
buttonValue: "Send OTP",
otpGeneratedMessage: null,
otpInput: {
isOtpMode: false,
isVerifying: false,
otpToken: null,
currentVerifiedMobile: null
}
};
},
methods: {
async sendVerificationCode() {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/todos/1"
);
if (data.userId) {
this.otpGeneratedMessage = "some message from server";
this.otpInput.isOtpMode = true; //to show otp input field(child component)
}
},
handleCompleteOtp(value) {
console.log("called");
this.otpInput = value;
}
}
};
</script>
Here is the child component
<template>
<div>
<div v-if="!isVerifying">
<input id="otp" class="input-fied" name="otpcode" placeholder="Enter your otp" type="number">
<input @click.prevent="this.verifyOtp" value="buttonValue" class="otp-btn" type="button">
<p style="margin-top: 2%">{{ message }}</p>
</div>
<div v-else="isVerifying">
<p>Please wait</p>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
props: {
message: {
type: String,
default: ""
},
mobileNumber: {
type: String,
default: null
}
},
data() {
return {
isVerifying: false
};
},
methods: {
async verifyOtp() {
/* Disable inputs & show loading */
this.isVerifying = true;
this.respondToParent({
otpToken: null,
mobileNumber: this.mobileNumber,
isVerifying: this.isVerifying,
isOtpMode: false
});
/* Send verify request to server */
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/todos/1"
);
/* If success & valid hide in parent send verified flag to parent */
/* If success & invalid otp show error */
this.isVerifying = false;
if (data.userId) {
this.respondToParent({
otpToken: "token from a success response",
mobileNumber: this.mobileNumber,
isVerifying: false,
isOtpMode: false
});
} else {
this.respondToParent({
OtpToken: null,
mobileNumber: this.mobileNumber,
isVerifying: this.isVerifying,
isOtpMode: false
});
}
/* If error show retry button with error message */
},
respondToParent(value) {
this.$emit("handleComplete", {
otpToken: value.otpToken,
mobileNumber: this.mobileNumber,
isVerifying: value.isVerifying,
isOtpMode: value.isOtpMode
});
}
}
};
</script>
I cant figure out why its not getting updated the second time even though its getting called both times from child. Somehow managed to replicate the same on sandbox environment. code in codesandbox
Upvotes: 0
Views: 1188
Reputation: 22413
The first time you called this.respondToParent
, it sets otpInput.isOtpMode
to false, so GeneralOtp
will not be rendered because you're using v-if:
<div v-if="otpInput.isOtpMode">
<GeneralOtp
:message="otpGeneratedMessage"
:mobileNumber="this.mobileNumber"
@handleComplete="handleCompleteOtp"
/>
</div>
You can check it will be called 2 times if you change your first this.respondToParent
to
this.respondToParent({
otpToken: null,
mobileNumber: this.mobileNumber,
isVerifying: this.isVerifying,
isOtpMode: true
});
(Note that isOtpMode: true
)
I think you should keep isOtpMode
is true in the first call and use isVerifying
to disable something in the parent component as you said.
Demo here
Upvotes: 2