As you did with CoffeeRun, you will create an object to manage the form element in the DOM. This will be the ChatForm class. Using ES6 classes will make your code a bit more readable than your code from CoffeeRun.
Creating a ChatForm instance and initializing its event handlers will occur in two separate steps, because a constructor’s job should only be to set the properties of an instance. Other work (like attaching event listeners) should be done in other methods.
Define ChatForm in dom.js with a constructor that accepts selectors. In the constructor, add properties for the elements the instance will need to track.
import $ from 'jquery'; class ChatForm { constructor(formSel, inputSel) { this.$form = $(formSel); this.$input = $(inputSel); } }
Next, add an
init method that will associate a callback with
the form’s submit
event.
... class ChatForm { constructor(formSel, inputSel) { this.$form = $(formSel); this.$input = $(inputSel); } init(submitCallback) { this.$form.submit((event) => { event.preventDefault(); let val = this.$input.val(); submitCallback(val); this.$input.val(''); }); this.$form.find('button').on('click', () => this.$form.submit()); } }
In the init method, you used an arrow function for the submit handler. Inside the arrow function, you prevented the default form action, retrieved the value from the input field, and then passed that value to submitCallback. Finally, you reset the value of the input.
To make sure the form submits when the button is clicked,
you added a click handler that causes the form to fire its
submit
event. You did this by getting the form element
with jQuery and then calling jQuery’s submit
method. You used the single-expression version of the arrow function,
allowing you to omit the curly braces.
To make this module useful, you need to export
ChatForm.
In the previous chapter, you used export default
for this purpose.
This allowed you to export a single value for the module.
In some cases, you used a plain JavaScript object to package up multiple values within that single default value.
In this chapter, you will use named exports to export multiple named values instead of a single default value.
Export ChatForm as a named value to users of this module by
adding the export
keyword just before the class
declaration.
... export class ChatForm { constructor(formSel, inputSel) { this.$form = $(formSel); this.$input = $(inputSel); } ...
Easy enough. Now to import ChatForm in app.js.
In Ottergram and CoffeeRun, you used the var
keyword
for selector strings. In ES6, you can declare constants for this
purpose, because the values of the strings will not change. Like let
,
const
is block-scoped, meaning that it is visible
to any code inside the same set of curly braces. When it is outside all curly braces
(which will be the case here), it is visible to any code in the same file.
In app.js, import the ChatForm class and create constants for the form’s selector and message input selector. Also, create an instance of ChatForm in ChatApp’s constructor function.
import socket from './ws-client'; import {ChatForm} from './dom'; const FORM_SELECTOR = '[data-chat="chat-form"]'; const INPUT_SELECTOR = '[data-chat="message-input"]'; class ChatApp { constructor() { this.chatForm = new ChatForm(FORM_SELECTOR, INPUT_SELECTOR); socket.init('ws://localhost:3001'); socket.registerOpenHandler(() => { let message = new ChatMessage('pow!'); socket.sendMessage(message.serialize()); }); socket.registerMessageHandler((data) => { console.log(data); }); } } ...
When you imported ChatForm, you wrapped it in
curly braces: {ChatForm}
. This signifies a named import.
The named import for ChatForm declares a local variable
named ChatForm
and binds it to the value from the
dom
module of the same name.
In the last chapter, you sent a dummy message:
"pow!"
.
Now you are ready to send real form data from ChatForm.
Inside the socket.registerOpenHandler
callback, you will initialize the
ChatForm instance.
It is important to do this after the socket is open,
instead of initializing immediately after creating the instance. By waiting, you prevent
your user from entering chat messages before they can actually be
sent to the server. (That would be a bad thing.)
Remember that ChatForm’s init method accepts a callback. This callback will be used to handle form submissions.
In app.js, delete your dummy message code and replace it
with a call to ChatForm.init
, passing it a callback that
sends message data coming from ChatForm
to your socket.
... class ChatApp { constructor() { this.chatForm = new ChatForm(FORM_SELECTOR, INPUT_SELECTOR); socket.init('ws://localhost:3001'); socket.registerOpenHandler(() => {let message = new ChatMessage('pow!');socket.sendMessage(message.serialize());this.chatForm.init((data) => { let message = new ChatMessage(data); socket.sendMessage(message.serialize()); }); }); socket.registerMessageHandler((data) => { console.log(data); }); } } ...
Let’s look at what ChatApp is doing now. First, it opens the socket connection to the server. When the connection is open, ChatApp initializes your instance of ChatForm with a form submission callback.
Now, when the user submits a message in the form the ChatForm instance will take that data and send it to ChatApp’s callback, and the callback will then package it up as a ChatMessage and send it to the WebSockets server.
3.139.80.209