-
-
Save richard-flosi/b6cdba782576447fcc9789f6cdfe2e31 to your computer and use it in GitHub Desktop.
<html> | |
<head> | |
<script> | |
customElements.define("star-wars-planets", class extends HTMLElement { | |
constructor() { | |
super(); | |
this.attachShadow({ mode: "open" }); | |
} | |
static get observedAttributes() { return ["loading", "planets"]; } | |
get loading() { | |
return JSON.parse(this.getAttribute("loading")); | |
} | |
set loading(v) { | |
this.setAttribute("loading", JSON.stringify(v)); | |
} | |
get planets() { | |
return JSON.parse(this.getAttribute("planets")); | |
} | |
set planets(v) { | |
this.setAttribute("planets", JSON.stringify(v)); | |
} | |
async fetchPlanets(url) { | |
this.loading = true; | |
const response = await fetch(url); | |
const json = await response.json(); | |
this.planets = json; | |
this.loading = false; | |
} | |
async connectedCallback() { | |
this.shadowRoot.addEventListener("click", (event) => { | |
const name = event.srcElement.id; | |
if (this[name]) { | |
this[name](); | |
} | |
}); | |
await this.fetchPlanets("https://swapi.co/api/planets"); | |
} | |
disconnectedCallback() { | |
} | |
attributeChangedCallback(attrName, oldVal, newVal) { | |
this.render(); | |
} | |
next() { | |
this.fetchPlanets(this.planets.next); | |
} | |
previous() { | |
this.fetchPlanets(this.planets.previous); | |
} | |
renderPrevious() { | |
if (this.planets.previous) { | |
return `<div id="previous">Previous</div>`; | |
} else { | |
return `<div>No previous planets.</div>`; | |
} | |
} | |
renderNext() { | |
if (this.planets.next) { | |
return `<div id="next">Next</div>`; | |
} else { | |
return `<div>No more planets.</div>`; | |
} | |
} | |
render() { | |
if (this.loading) { | |
this.shadowRoot.innerHTML = `Loading...`; | |
} else { | |
this.shadowRoot.innerHTML = ` | |
<span> | |
<h3><slot name="title">Star Wars Planets</slot></h3> | |
<div>Count: ${this.planets.count}</div> | |
${this.renderPrevious()} | |
${this.renderNext()} | |
<table> | |
<tr> | |
<th>Name</th> | |
<th>Terrain</th> | |
<th>Population</th> | |
<th>Climate</th> | |
<th>Diameter</th> | |
<th>Gravity</th> | |
<th>Orbital Period</th> | |
<th>Rotation Period</th> | |
<th>Surface Water</th> | |
<th>URL</th> | |
</tr> | |
${this.planets.results.map((planet) => { | |
return ` | |
<tr> | |
<td>${planet.name}</td> | |
<td>${planet.terrain}</td> | |
<td>${planet.population}</td> | |
<td>${planet.climate}</td> | |
<td>${planet.diameter}</td> | |
<td>${planet.gravity}</td> | |
<td>${planet.orbital_period}</td> | |
<td>${planet.rotation_period}</td> | |
<td>${planet.surface_water}</td> | |
<td>${planet.url}</td> | |
</tr> | |
`; | |
}).join("")} | |
</table> | |
</span> | |
`; | |
} | |
} | |
}); | |
</script> | |
</head> | |
<body> | |
<star-wars-planets> | |
<span slot="title">My Custom Star Wars</span> | |
</star-wars-planets> | |
</body> | |
</html> |
This may be the only example on the web of connectedCallback
being used asynchronously, helped me massively! 👍
Cool. Glad this was useful. I also have a repository with more code here: https://github.com/richard-flosi/star-wars-planets
Awesome! 😀
Thanks for the excellent example!
Great example, exactly what I was looking for. Thanks for sharing. 👍🏼
Thanks a lot!!! ✌️
Thank you so much!!!
how to deal with if I want to do thomething after async connectedCallback? PLEASE help)!!!!
@dixonnixon add any event listeners you need in connectedCallback and handle attribute changes in attributionChangedCallback. attributeChangeCallback will be called with the attribution name that changed, the old value, and the new value.
@richard-flosi, huh, I decided to use another class as a View to hold and store event listeners
Great, thank you! That use of async connectedCallback()
was very helpful! 🙂
This is some very nice work. Simple, clean implementation that makes the intention of each feature easily understandable.
@mattbontrager thanks! I'm glad this is still useful. I have a related blog post that is more recent which may provide additional information.
Check out: Learn the Lifecycle of a Web Component by Building a Custom Element as well.
That's the example I was looking for! Thanks!