This guide explains how to create a single repeatable web component that dynamically handles multiple data points from a JSON file. The component will:
- Populate
<user-name></user-name>with a user's name. - Render search results inside
<search-results>with dynamic rows based on available vertical space. - Populate
<label>elements inside<nav>for accessible tab navigation. - Render paragraphs inside
<section>elements.
The component will use modern CSS for layout and accessibility, minimizing JavaScript usage.
The following JSON structure will be used to populate our web component:
{
"user": { "name": "John Doe" },
"searchResults": [
{ "id": 1, "text": "First Result" },
{ "id": 2, "text": "Second Result" },
{ "id": 3, "text": "Third Result" }
],
"tabs": [
{ "id": "tab1", "label": "Home", "content": "Welcome to Home" },
{ "id": "tab2", "label": "About", "content": "About Section" },
{ "id": "tab3", "label": "Contact", "content": "Contact Us" }
]
}Create a reusable Web Component that processes this JSON data and populates the HTML structure.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Component Example</title>
<script>
class DynamicData extends HTMLElement {
async connectedCallback() {
const response = await fetch('data.json');
const data = await response.json();
if (this.tagName === 'USER-NAME') {
this.innerText = data.user.name;
}
if (this.tagName === 'SEARCH-RESULTS') {
this.innerHTML = `<div class="results-container">` + data.searchResults.map(
item => `<p class="result">${item.text}</p>`
).join('') + `</div>`;
}
if (this.tagName === 'NAV') {
this.innerHTML = data.tabs.map(
tab => `
<input type="radio" id="${tab.id}" name="tabs" hidden>
<label for="${tab.id}">${tab.label}</label>
`
).join('');
}
if (this.tagName === 'SECTION') {
this.innerHTML = data.tabs.map(
tab => `<p>${tab.content}</p>`
).join('');
}
}
}
customElements.define('user-name', DynamicData);
customElements.define('search-results', DynamicData);
customElements.define('nav', DynamicData);
customElements.define('section', DynamicData);
</script>
<style>
nav {
display: flex;
gap: 1rem;
}
label {
cursor: pointer;
padding: 0.5rem;
background: #ddd;
}
input:checked + label {
background: #aaa;
}
section p {
display: none;
}
input:checked ~ section p {
display: block;
}
search-results {
display: block;
max-height: 50vh;
overflow: auto;
}
.results-container {
display: grid;
grid-template-rows: repeat(auto-fill, minmax(1rem, 1fr));
}
</style>
</head>
<body>
<h1>Dynamic Web Component</h1>
<p>Hello, <user-name></user-name>!</p>
<h2>Search Results</h2>
<search-results></search-results>
<h2>Tabs</h2>
<nav></nav>
<section></section>
</body>
</html>- The Web Component fetches
data.jsonand determines the appropriate rendering logic based on its tag.
- Extracts
data.user.nameand inserts it inside the tag.
- Iterates over
data.searchResultsto create paragraph elements dynamically. - Uses
grid-template-rows: repeat(auto-fill, minmax(1rem, 1fr));for responsive rendering based on available space. - Encapsulates search results in
.results-containerto provide structured styling and allow dynamic row allocation.
- Iterates over
data.tabsto create radio button inputs with corresponding labels for accessible tab navigation. - Uses CSS selectors to control visibility based on which radio input is checked.
This solution:
- Uses a single Web Component to manage different data needs.
- Dynamically renders JSON data inside semantic elements.
- Uses modern CSS techniques like
auto-filland:checkedselectors for usability and responsiveness. - Keeps the HTML minimal while ensuring accessibility and a seamless user experience.
This method creates a scalable, maintainable component architecture that enhances both development efficiency and user experience.