Model–view–controller separates an application into three responsibilities: the model holds and manages data, the view presents it, and the controller handles interaction between them. In a web application, the view commonly contains HTML and CSS, while the controller reacts to UI events and updates the model. section 14.4
Use the separation to keep data in a predictable place rather than embedding large collections inside rendering components.
- Model: stores data, exposes useful accessors, and can handle operations such as remote retrieval, persistence, editing, and derived values. section 14.4
- View: renders the visual interface, such as a Web Component template containing HTML and CSS. section 14.4
- Controller: responds to clicks and input changes, then coordinates updates between the view and model. section 14.4
Exercise library and workout plans
An exercise-library component renders data from an exercise-library model instead of receiving a large inline array. A central workout-plan model provides saved plans, save and load operations, clearing, editing, exercise access, and total duration. Components call that model when users click exercises, save a plan, clear it, or choose a saved plan; localStorage supplies persistence. section 14.4
Listing 14.10. Central data model for workout plan
export default {
get saved() { #1
const savedplans = [];
Object.keys(localStorage).forEach(function(key){
savedplans.push(key);
});
return savedplans;
},
save(name) { #2
localStorage.setItem(name, JSON.stringify(this._currentWorkout));
},
load(key) { #3
this._currentWorkout = JSON.parse(localStorage.getItem(key));
},
edit(id, key, value) { #4
let exercise;
for (let c = 0; c < this._currentWorkout.length; c++) {
if (id === this._currentWorkout[c].id) {
exercise = this._currentWorkout[c];
exercise[key] = value;
}
}
},
add(exercise) { #5
if (!this._currentWorkout) {
this._currentWorkout = [];
}
exercise.id = this.createID();
this._currentWorkout.push(exercise);
},
remove(id) { #6
if (!this._currentWorkout) { return; }
for (let c = 0; c < this._currentWorkout.length; c++) {
if (this._currentWorkout[c].id === id) {
const deleted = this._currentWorkout.splice(c, 1);
return;
}
}
}
}
Browse the central workout-plan model to see persistence, loading, editing, clearing, and derived data gathered behind one interface. section 14.4



