Question

Describe, using code fragments, and concrete examples, how to implement the Model View Controller (MVC) design pattern, in relation to web development, using Javascript.

Describe, using code fragments, and concrete examples, how to implement the Model View Controller (MVC) design pattern, in relation to web development, using Javascript.

0 0
Add a comment Improve this question Transcribed image text
Answer #1

Before implementing the MVC classes in Javascript, the notification approach is need to be chosen. In JavaScript there is no special language construction or recommended interface on how the Publish-Subscribe pattern should be implemented. All implementations just use the function references. Most common of them is probably the EventEmitter implementation, which can be found in node.js for example. Two main methods of this implementations are "on" for adding event handler and "emit" for calling the event handlers for the specified event. The notifications can be added to the class by extending it from the EventEmitter or by adding methods that proxify calls to the internal instance of the EventEmitter.

class EventEmitter {
  constructor() {
    this._events = {};
  }
  on(evt, listener) {
    (this._events[evt] || (this._events[evt] = [])).push(listener);
    return this;
  }
  emit(evt, arg) {
    (this._events[evt] || []).slice().forEach(lsn => lsn(arg));
  }
}

The data of the component is just a list of items, in which one particular item can be selected and deleted. So, the model of the component is very simple - it consists of an array and a selected item index; and here it is:

/**
 * The Model. Model stores items and notifies
 * observers about changes.
 */
class ListModel extends EventEmitter {
  constructor(items) {
    super();
    this._items = items || [];
    this._selectedIndex = -1;
  }

  getItems() {
    return this._items.slice();
  }

  addItem(item) {
    this._items.push(item);
    this.emit('itemAdded', item);
  }

  removeItemAt(index) {
    const item = this._items.splice(index, 1)[0];
    this.emit('itemRemoved', item);
    if (index === this._selectedIndex) {
      this.selectedIndex = -1;
    }
  }

  get selectedIndex () {
    return this._selectedIndex;
  }

  set selectedIndex(index) {
    const previousIndex = this._selectedIndex;
    this._selectedIndex = index;
    this.emit('selectedIndexChanged', previousIndex);
  }
}

Before designing the View we need to fix the UI structure of the component. There are numerous alternatives of interface, but for the purpose of this article the most simple one will suit better. Let's keep the items in a Listbox control and add two buttons nearby: "plus" button for adding items and "minus" for removing selected item. ListBox will provide us with the low-level machinery for selecting an item and navigating. A View class is tightly bound to a Controller class, which "... handles the input event from the user interface, often via a registered handler or callback" (from wikipedia.org).

Here are the View and Controller classes:

/**
 * The View. View presents the model and provides
 * the UI events. The controller is attached to these
 * events to handle the user interaction.
 */
class ListView extends EventEmitter {
  constructor(model, elements) {
    super();
    this._model = model;
    this._elements = elements;

    // attach model listeners
    model.on('itemAdded', () => this.rebuildList())
      .on('itemRemoved', () => this.rebuildList());

    // attach listeners to HTML controls
    elements.list.addEventListener('change',
      e => this.emit('listModified', e.target.selectedIndex));
    elements.addButton.addEventListener('click',
      () => this.emit('addButtonClicked'));
    elements.delButton.addEventListener('click',
      () => this.emit('delButtonClicked'));
  }

  show() {
    this.rebuildList();
  }

  rebuildList() {
    const list = this._elements.list;
    list.options.length = 0;
    this._model.getItems().forEach(
      item => list.options.add(new Option(item)));
    this._model.selectedIndex = -1;
  }
}

/**
 * The Controller. Controller responds to user actions and
 * invokes changes on the model.
 */
class ListController {
  constructor(model, view) {
    this._model = model;
    this._view = view;

    view.on('listModified', idx => this.updateSelected(idx));
    view.on('addButtonClicked', () => this.addItem());
    view.on('delButtonClicked', () => this.delItem());
  }

  addItem() {
    const item = window.prompt('Add item:', '');
    if (item) {
      this._model.addItem(item);
    }
  }

  delItem() {
    const index = this._model.selectedIndex;
    if (index !== -1) {
      this._model.removeItemAt(index);
    }
  }

  updateSelected(index) {
    this._model.selectedIndex = index;
  }
}

And of course, the Model, View, and Controller classes should be instantiated:

Your favourite JavaScript technologies:<br>
<select id="list" size="10" style="width: 17em"></select><br>
<button id="plusBtn">  +  </button>
<button id="minusBtn">  -  </button>
window.addEventListener('load', () => {
  const model = new ListModel(['node.js', 'react']),
    view = new ListView(model, {
      'list' : document.getElementById('list'),
      'addButton' : document.getElementById('plusBtn'), 
      'delButton' : document.getElementById('minusBtn')
    }),
    controller = new ListController(model, view);

  view.show();
});
Add a comment
Know the answer?
Add Answer to:
Describe, using code fragments, and concrete examples, how to implement the Model View Controller (MVC) design pattern, in relation to web development, using Javascript.
Your Answer:

Post as a guest

Your Name:

What's your source?

Earn Coins

Coins can be redeemed for fabulous gifts.

Not the answer you're looking for? Ask your own homework help question. Our experts will answer your question WITHIN MINUTES for Free.
Similar Homework Help Questions
ADVERTISEMENT
Free Homework Help App
Download From Google Play
Scan Your Homework
to Get Instant Free Answers
Need Online Homework Help?
Ask a Question
Get Answers For Free
Most questions answered within 3 hours.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT