Image

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

3 min read
Last update: December 19, 2021

Flexible Events

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

In the last lesson we created the button toolbar for our email-reading modal.

<div class="email-display">
    <div class="toolbar">
        <button @click="toggleArchive">{{email.archived ? 'Move to Inbox (e)' : 'Archive (e)'}}</button>
        <button @click="toggleRead">{{email.read ? 'Mark Unread (r)' : 'Mark Read (r)'}}</button>
        <button @click="goNewer">Newer (k)</button>
        <button @click="goOlder">Older (j)</button>
    </div>

    ...
</div>

There are four actions, but using the tools available in the MailView component, we can only fully accomplish toggleRead. We need to either pass down a bunch of tools from the MailTable component, or pass up instructions to the MailTable component via an event.

We’ll do the latter.

We’ll use an event called changeEmail, and we’ll tell it what needs to get done by passing arguments.

Let’s first emit the event, using arguments to make a ‘wish list’ of what we want to get done. We’ll start with toggleArchive and toggleRead .

let toggleRead = () => emit('changeEmail', {toggleRead: true, save: true})
let toggleArchive = () => emit('changeEmail', {toggleArchive: true, save: true, closeModal: true})

We’re sending four different options: toggleRead, save , toggleArchive , and closeModal .

Our changeEmail event will have to handle all of those correctly.

Now we’ll fill out the other two methods from the buttons, and add two more that are just keyboard shortcuts. We’ll need just one more option for the event: changeIndex.

setup({changeEmail}){
let toggleRead = () => emit('changeEmail', {toggleRead: true, save: true})
let toggleArchive = () => emit('changeEmail', {toggleArchive: true, save: true, closeModal: true})
let goNewer = () => emit('changeEmail', {changeIndex: -1})
let goOlder = () => emit('changeEmail', {changeIndex: 1})
let goNewerAndArchive = () => emit('changeEmail', {changeIndex: -1, toggleArchive: true})
let goOlderAndArchive = () => emit('changeEmail', {changeIndex: 1, toggleArchive: true})

useKeydown([
{key: 'e', fn: toggleArchive},
{key: 'r', fn: toggleRead},
{key: 'k', fn: goNewer},
{key: 'j', fn: goOlder},
{key: '[', fn: goNewerAndArchive},
{key: ']', fn: goOlderAndArchive}
])

return {
format,
marked,
toggleArchive,
toggleRead,
goNewer,
goOlder,
}
}

Then we’ll feed in the changeEmail event to the MailView component.

<MailView v-if="openedEmail" :email="openedEmail" @changeEmail="changeEmail" />

Then we’ll create the changeEmail function itself. The argument names make them self-explanatory, and grouping them in an object means we can include or not include as we like, without worrying about order.

Also note that the openEmail method had to change, to account for the possibility of a null email (such as when hitting ‘older’ on the oldest email)

methods: {
changeEmail({toggleRead, toggleArchive, save, closeModal, changeIndex}) {
let email = this.openedEmail;
if(toggleRead) { email.read = !email.read }
if(toggleArchive) { email.archived = !email.archived }
if(save) { this.updateEmail(email) }
if(closeModal) { this.openedEmail = null; }

if(changeIndex) {
let emails = this.unarchivedEmails
let currentIndex = emails.indexOf(this.openedEmail)
let newEmail = emails[currentIndex + changeIndex]
this.openEmail(newEmail)
}
},
openEmail(email){
this.openedEmail = email;

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

And now we’ve got a great set of actions we can perform on the email display modal - both through clicking buttons and through using keyboard shortcuts.

We’ve also got a useful pattern for communicating requests from a child component to a parent component.

For the ending code for this lesson, switch to branch: https://github.com/Code-Pop/build-gmail-clone-with-vue-3/tree/video-10-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.