Image

build-a-gmail-clone-with-vue-3

3 min read
Last update: December 19, 2021

Opening an Email

For the starting code for this lesson, switch to branch: https://github.com/Code-Pop/build-gmail-clone-with-vue-3/tree/video-5-start

What we’re going to be doing in this lesson is make it so clicking on an email opens the email, instead of just marking it as read. It’ll open below the email table, and then in the next lesson we’ll make it open in a modal.

Let’s start by renaming the readEmail method to openEmail.

Then, in the openEmail method, we’ll set the openedEmail variable as the selected email.

openEmail(email){
email.read = true
axios.put(`http://localhost:3000/emails/${email.id}`, email)
this.openedEmail = email;
},

To make that work, we’ll need to return the openedEmail variable as part of our setup. It will default to null.

async setup(){
let {data: emails} = await axios.get('http://localhost:3000/emails');
return {
format,
emails,
openedEmail: null
}
},

Then, before investing heavily in styling, we’ll show that what we’ve got set up works.

<div v-if="openedEmail">{{openedEmail.subject}}</div>

https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2F5_1.jpg?alt=media&token=241ba4b8-71f9-48f3-8941-5b4690fb3923

Once we’ve confirmed that by clicking around a bit, it’s time to create the MailView component.

We’ll start by treating it as if it already exists and using it in the MailTable component.

<MailView v-if="openedEmail" :email="openedEmail" />
import { format } from 'date-fns';
import axios from 'axios';
import MailView from '@/components/MailView.vue';

export default {
//...
components: {
MailView
},
//...
}

Then we’ll create a basic version of that component.

<template>
    <div class="email-display">
        <h2 class="mb-0">Subject: <strong>{{email.subject}}</strong></h2>
        <div><em>From {{email.from}} on {{email.sentAt}}</em></div>
        <div>{{email.body}}</div>
    </div>
</template>

<script>
    export default {
        props: {
            email: {
                type: Object,
                required: true
            }
        }
    }
</script>

Notice that the way we use props stays the same. The only difference is that you can access your props in the setup function, as the first argument. Note that we will not be using the props in the setup function in this video.

export default {
// for demonstration purposes only
setup(props) {
let email = props.email
//...
},
props: { ... }
}

Now we should be able to see it displaying.

https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2F5_2.jpg?alt=media&token=521c22c1-7549-4278-b178-73ea387061d2

We’re now seeing the entire email below the table, but there are some data display issues. Let’s fix those.

First, we’ll fix the sentAt display using the format method from date-fns. We could use the data and setup functions for this, and they’re of equivalent complexity, so let’s use the more flexible setup function.

import { format } from 'date-fns'

export default {
setup(){
return {
format,
}
},
props: { ... }
}
<div><em>From {{email.from}} on {{format(new Date(email.sentAt), 'MMM do yyyy')}}</em></div>

With that improved, now let’s do something similar for the multi-paragraph email body. We’ll use the marked library, which is already in the package.json for the starter code. It will turn markdown into html that can be fed into the v-html directive.

import { format } from 'date-fns';
import marked from 'marked';

export default {
setup(){
return {
format,
marked
}
},
props: { ... }
}
<div v-html="marked(email.body)" />

Our email is showing up nicely now.

https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2F5_3.jpg?alt=media&token=8b5cf135-19f0-4e9f-bccc-ae4a4367811e

In the next video, we’re going to put this email display in a modal.

For the ending code for this lesson, switch to branch: https://github.com/Code-Pop/build-gmail-clone-with-vue-3/tree/video-5-end

Jeffrey teaches an 8-week beginning Vue course with guaranteed results. Built on top of the VueMastery curriculum, with extra hands-on assignments and personal attention. You can find it here.