Skip to content

Instantly share code, notes, and snippets.

@efuller

efuller/list.js Secret

Last active Dec 11, 2018
Embed
What would you like to do?
Observable pattern in JavaScript
import Observer from "../lib/Observer";
class List extends Observer {
createMarkup(state) {
return `<ul>
${state.users.map(user => `<li>${user.name}</li>`).join("\n")}
</ul>`;
}
render(state, selector = "app") {
const markup = this.createMarkup(state);
const parent = document.getElementById(selector);
parent.innerHTML = markup;
}
// This method will be called by the Subject(state) whenever it updates.
// Notice how it prompts a re-render.
update(state) {
this.render(state, "user-list-container");
}
}
export default List;
class Observer {
// Gets called by the Subject::notify method.
update() {}
}
export default Observer;
import Subject from "./Subject";
class State extends Subject {
constructor() {
super();
this.state = {};
}
// Update the state.
// Calls the update method on each observer.
update(data = {}) {
this.state = Object.assign(this.state, data);
this.notify(this.state);
}
// Get the state.
get() {
return this.state;
}
}
export default State;
class Subject {
constructor() {
this.observers = [];
}
// Add an observer to this.observers.
addObserver(observer) {
this.observers.push(observer);
}
// Remove an observer from this.observers.
removeObserver(observer) {
const removeIndex = this.observers.findIndex(obs => {
return observer === obs;
});
if (removeIndex !== -1) {
this.observers = this.observers.slice(removeIndex, 1);
}
}
// Loops over this.observers and calls the update method on each observer.
// The state object will call this method everytime it is updated.
notify(data) {
if (this.observers.length > 0) {
this.observers.forEach(observer => observer.update(data));
}
}
}
export default Subject;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment