Creating the ChatForm Class

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.

Connecting ChatForm to the socket

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.136.186