Issue
I am currently working on a Website using Nuxt.js (Vue.js) and I am having trouble with my custom Alert Component.
I created a contact-form on my website that triggers a custom notification when the user enters wrong data or does not enter all required data. However, if the same error gets triggered twice (e.g. wrong phone number). The alert does not show a second time.
I have now tried to fix this for two days and ChatGPT can't help me either here. So I really hope that one of you knows why this might be happening.
My custom WarningAlert component:
<!-- WarningAlert.vue -->
<template>
<div v-if="show" class="overlay">
<div class="alert alert-warning" role="alert">
<div class="container">
<div class="alert-icon">
<i class="now-ui-icons ui-1_bell-53"></i>
</div>
<strong>{{ strongText }}</strong> {{ message }}
<button v-if="dismissible" type="button" class="close" @click="hideOverlay" aria-label="Close">
<span aria-hidden="true">
<i class="now-ui-icons ui-1_simple-remove"></i>
</span>
</button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
message: String,
type: String,
strongText: String,
dismissible: Boolean,
},
data() {
return {
show: false,
};
},
methods: {
hideOverlay() {
this.show = false;
},
showWarningAlert(message) {
// Show the warning alert with the provided message
this.message = message;
this.show = true;
// Hide the warning alert after 5 seconds (5000 milliseconds)
setTimeout(() => {
this.hideOverlay();
}, 5000);
},
hideWarningAlert() {
// Dismiss the warning alert
this.show = false;
this.message = '';
},
},
watch: {
message() {
// sets show true, after an update
this.show = true;
setTimeout(() => {
// delayed hiding 5000 Millisekunden (5 Seconds)
this.hideOverlay();
}, 5000);
},
},
mounted() {
this.showWarningAlert(this.message);
},
};
</script>
<style scoped>
.overlay {
position: fixed;
top: 50px;
left: 0;
width: 100%;
z-index: 1000;
display: flex;
justify-content: center;
align-items: flex-start;
padding: 20px;
}
.alert {
width: 70%;
}
</style>
Here is the contact form and the imported component:
<!-- Alert component -->
<WarningAlert v-if="showWarningAlert" :message="warningMessage" :type="'warning'" :strongText="'Warning!'"
:dismissible="true" @dismiss="dismissWarningAlert"></WarningAlert>
<!-- Contact Form -->
<div class="main">
<div class="contact-content">
<div class="container">
<div class="row">
<div class="col-md-5 ml-auto mr-auto">
<h2 class="title">Senden Sie uns eine Nachricht</h2>
<p class="description">Wir stehen Ihnen gerne zur Verfügung. Wir werden Ihnen innerhalb eines Werktages
antworten.
<br>
<br>
</p>
<form role="form" id="contact-form" @submit.prevent="submitForm" method="post">
<label>Ihr Name</label>
<fg-input required placeholder="Name..." v-model="form.firstName"
addon-left-icon="now-ui-icons users_circle-08"></fg-input>
<label>Email Adresse</label>
<fg-input required placeholder="Email..." v-model="form.email"
addon-left-icon="now-ui-icons users_circle-08" title="Please enter a valid email address"></fg-input>
<label>Telefon</label>
<fg-input required placeholder="Telefonnummer..." v-model="form.phone"
addon-left-icon="now-ui-icons tech_mobile"></fg-input>
<div class="form-group">
<label>Ihre Nachricht</label>
<textarea name="message" class="form-control" id="message" placehiolder="Nachricht..." v-model="form.message" rows="6"></textarea>
</div>
<div class="submit text-center">
<button class="btn btn-success btn-rounded" type="submit" round>Senden</button>
</div>
</form>
And finally the CSS of my submitForm() method, where the error probably lies (as the notification gets triggered here).
methods: {
async submitForm() {
// Initialisation
this.showWarningAlert = false;
this.warningMessage = '';
// Check if all relevant fields filled out
if (!this.form.firstName || !this.form.email || !this.form.phone) {
this.showWarningAlert = true;
this.warningMessage = 'Please fill out all required fields (Name, Email, Phone).';
return;
}
const emailRegex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (!this.form.email.match(emailRegex)) {
this.showWarningAlert = true;
this.warningMessage = 'Please enter a valid email address.';
return;
}
const phoneRegex = /^(\+\d{1,3})?\d{1,14}$/;
if (!this.form.phone.match(phoneRegex)) {
this.showWarningAlert = true;
this.warningMessage = 'Please enter a valid phone number.';
return;
}
// Send formulas if everything is validated
try {
const response = await axios.post('http://localhost:3005/send-email', this.form);
if (response.status === 200) {
console.log('Email sent successfully');
}
} catch (error) {
console.error('Error sending email:', error);
// Show warning if error
this.showWarningAlert = true;
this.warningMessage = 'Something went wrong. Please contact us via email.';
} finally {
// Reset Warning properties before leaving the method
this.showWarningAlert = false;
this.warningMessage = '';
}
},
dismissWarningAlert() {
// Dismiss the warning alert
this.showWarningAlert = false;
this.warningMessage = '';
}
},
Solution
Looks to me like you could save yourself some headaches by simply moving a few things around in your code.
Toggle State
The first thing that stands out to me is that you're storing the toggle state for your alert in two separate places - in the alert component itself (as this.show
) and also in the submitForm method for your form (as this.showWarningAlert
). Arguably, the best place to store the variable that represents the visibility state of your alert toggle is in the parent component, in this case the component that also contains your form. I'd recommend passing this variable through to the alert component via a prop and use the prop value in the v-if inside your alert component.
Is this.showWarningAlert
initialized in the parent context? If it is then great, you can pass this.showWarningAlert
in to the child (alert) component via props. Then if you want to change the toggle state, you can emit from the child component (see below) up to the parent component which holds the toggle state in a variable (i.e. this.showWarningAlert
)
No emits
Your alert component also appears to be missing an emit called 'dismiss', which according to your code is supposed to trigger your dismissWarningAlert method. I'd move all the methods that toggle the alert visibility up to the parent component (in the same context where the toggle state this.showWarningAlert
is stored) and if you want to automatically time-out the visibility of your alert, you can set a watch on the value of the visibility prop coming in to the alert and set a setTimeout method whenever the value changes to true
.
Also...
I also noticed that you are using mixed quotes when passing strings as props to your alert component. You can drop the :
on the type
and strongText
attributes of your alert component, as well as the single quotes inside the double quotes... (i.e. type="warning" strongText="Warning!"
) It will make those attributes look a little cleaner and you won't be squinting to double-check you've got the right type of quotation in the right place ;)
I hope some or all of the above helped in some way!
Answered By - CJHolowatyj
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.