You can use the MVC pattern for Custom Elements just like with standard Javascript.
Define:
- one
object (or a class) for the Controller
- one for the Model
- one for the View
There are many ways to define and to interconnect the Model, View and Controller.
Custom Element specific
Adapted to the Custom Element, you can either:
- define the Custom Element class (extending
HTMLElement) as the Controller
- define the Custom Element class as the View
- define the the Model, View and Controller inside the Custom Element
class
- define the 3 entities outside the Custom Element
class
- etc.
Example
In the minimalist example implemented below:
- the Custom Element
class defines the Controller
- the Model is declared in the Controller as a
function
- then the View is declared in the Controller as a
function, too
This way the View can access the Model (for data reading) and the Controller directly.
//CONTROLLER
class PersonController extends HTMLElement {
connectedCallback() {
let controller = this
let elem = this
//MODEL
function PersonModel () {
//Model API
this.load = async id => {
let res = await fetch( `https://reqres.in/api/users/${id}` )
let json = await res.json()
Object.assign( this, json.data )
controller.updateView()
}
}
let model = new PersonModel
//VIEW
function PersonView () {
elem.innerHTML = `
Id : <input id=index type=number>
<div id=card>Loading data
</div>`
let card = elem.querySelector( 'div#card' )
let index = elem.querySelector( 'input#index' )
index.onchange = () => controller.init( index.value)
//View API
this.update = () => {
card.innerHTML = `
<div>Name : ${model.first_name} ${model.last_name}</div>
<div><img src=${model.avatar}></div>`
index.value = model.id
}
}
let view = new PersonView
//Controller API
this.init = id => model.load( id )
this.updateView = () => view.update()
//Init with some data
this.init( 4 )
}
}
customElements.define( 'person-card', PersonController )
person-card { display: inline-block ; background-color: lightblue }
person-card input { width: 50 }
<person-card></person-card>
This example creates a <person-card> element with the MVC pattern that will fetch some data from a REST web service (at reqres.in) and show a person's name, id, and avatar.