I currently have a significant amount of HTML inside a div which is generated within an iteration from a GET request to my .net core server.
Some of the values in the HTML is dynamic data returned from the server.
I've added a button to my website, which when pressed, makes an AJAX call to the server to return a JSON object representing the dynamic values for the next iteration.
So, I would like the JavaScript to add a new div to the DOM, which is the same, and has my dynamic values populated based on the JSON response.
For context, the DIV looks like this (which is from a bootstrap template I purchased):
<div class="card">
<!-- Card header START -->
<div class="card-header border-0 pb-0">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center">
<!-- Avatar -->
<div class="avatar me-2">
<a href="#!"> <img class="avatar-img rounded-circle" src="@post.ProfileImageUrl" alt="profile picture"> </a>
</div>
<!-- Info -->
<div>
<div class="nav nav-divider">
<h6 class="nav-item card-title mb-0"> <a href="#!"> @post.ProfileName </a></h6>
<span class="nav-item small"> @post.PostTime</span>
</div>
</div>
</div>
<!-- Card feed action dropdown START -->
<div class="dropdown">
<a href="#" class="text-secondary btn btn-secondary-soft-hover py-1 px-2" id="cardFeedAction" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-three-dots"></i>
</a>
<!-- Card feed action dropdown menu -->
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="cardFeedAction">
<li><a class="dropdown-item" href="#"> <i class="bi bi-bookmark fa-fw pe-2"></i>Save post</a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-person-x fa-fw pe-2"></i>Unfollow lori ferguson </a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-x-circle fa-fw pe-2"></i>Hide post</a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-slash-circle fa-fw pe-2"></i>Block</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-flag fa-fw pe-2"></i>Report post</a></li>
</ul>
</div>
<!-- Card feed action dropdown END -->
</div>
</div>
<!-- Card header END -->
<!-- Card body START -->
<div class="card-body">
<p><strong>@post.PostBody</strong></p>
<!-- Card img -->
<img class="card-img img-fluid" src="@post.PostImageUrl" alt="Post">
<!-- Feed react START -->
<ul class="nav nav-stack py-3 small">
<li class="nav-item">
<a class="nav-link active" href="#!"> <i class="bi bi-hand-thumbs-up-fill pe-1"></i>Liked (56)</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!"> <i class="bi bi-chat-fill pe-1"></i>Comments (12)</a>
</li>
<!-- Card share action START -->
<li class="nav-item dropdown ms-sm-auto">
<a class="nav-link mb-0" href="#" id="cardShareAction" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-reply-fill flip-horizontal ps-1"></i>Share (3)
</a>
<!-- Card share action dropdown menu -->
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="cardShareAction">
<li><a class="dropdown-item" href="#"> <i class="bi bi-envelope fa-fw pe-2"></i>Send via Direct Message</a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-bookmark-check fa-fw pe-2"></i>Bookmark </a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-link fa-fw pe-2"></i>Copy link to post</a></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-share fa-fw pe-2"></i>Share post via …</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#"> <i class="bi bi-pencil-square fa-fw pe-2"></i>Share to News Feed</a></li>
</ul>
</li>
<!-- Card share action END -->
</ul>
</div>
<!-- Card body END -->
<!-- Card footer START -->
<div class="card-footer border-0 pt-0">
<!-- Load more comments -->
<a href="#!" role="button" class="btn btn-link btn-link-loader btn-sm text-secondary d-flex align-items-center" data-bs-toggle="button" aria-pressed="true">
<div class="spinner-dots me-2">
<span class="spinner-dot"></span>
<span class="spinner-dot"></span>
<span class="spinner-dot"></span>
</div>
Load more comments
</a>
</div>
<!-- Card footer END -->
</div>
<!-- Card feed item END -->
Question:
There's a lot of HTML here. What's the best way to build this out in Javascript? Is it just a case of biting the bullet and writing all of the JS code to create each element/class?
Would this be the best practice? Because it effectively means I'm maintaining the HTML markup in two places..
Thank you..!
I usually save the html of the template to be rendered inside an hidden element. Then I can always access it using that element.innerHTML
. You could use specialized script
tag instead. But the innerHTML
part is the same.
After having the HTML as string you have 2 options
innerHTML
to the target container.html
(see function below) then append it and manipulate it otherwise.// render 5 cards
for (var i = 0; i < 5; i++) {
var html = document.querySelector("#card-template").innerHTML;
var elem = elemFromString(html)
// change something
elem.querySelector(".card-body>p strong").innerText = "card " + i
// append
document.querySelector("#container").append(elem)
}
// usefull utility
function elemFromString(html) {
var dummy = document.createElement("div");
dummy.innerHTML = html.trim();
if (dummy.children.length > 1) {
console.error("expecting one wrapping element for html. will return only firstChild")
}
var result = dummy.firstChild;
result.parentNode.removeChild(result)
return result;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<div id="container">
</div>
<div id="card-template" style="display:none">
<div class="card">
<!-- Card header START -->
<div class="card-header border-0 pb-0">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center">
<!-- Avatar -->
<div class="avatar me-2">
<a href="#!"> <img class="avatar-img rounded-circle" src="@post.ProfileImageUrl" alt="profile picture"> </a>
</div>
<!-- Info -->
<div>
<div class="nav nav-divider">
<h6 class="nav-item card-title mb-0"> <a href="#!"> @post.ProfileName </a></h6>
<span class="nav-item small"> @post.PostTime</span>
</div>
</div>
</div>
<!-- Card feed action dropdown START -->
<div class="dropdown">
<a href="#" class="text-secondary btn btn-secondary-soft-hover py-1 px-2" id="cardFeedAction" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-three-dots"></i>
</a>
<!-- Card feed action dropdown menu -->
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="cardFeedAction">
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-bookmark fa-fw pe-2"></i>Save post</a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-person-x fa-fw pe-2"></i>Unfollow lori ferguson </a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-x-circle fa-fw pe-2"></i>Hide post</a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-slash-circle fa-fw pe-2"></i>Block</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-flag fa-fw pe-2"></i>Report post</a>
</li>
</ul>
</div>
<!-- Card feed action dropdown END -->
</div>
</div>
<!-- Card header END -->
<!-- Card body START -->
<div class="card-body">
<p><strong>@post.PostBody</strong></p>
<!-- Card img -->
<img class="card-img img-fluid" src="@post.PostImageUrl" alt="Post">
<!-- Feed react START -->
<ul class="nav nav-stack py-3 small">
<li class="nav-item">
<a class="nav-link active" href="#!"> <i class="bi bi-hand-thumbs-up-fill pe-1"></i>Liked (56)</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!"> <i class="bi bi-chat-fill pe-1"></i>Comments (12)</a>
</li>
<!-- Card share action START -->
<li class="nav-item dropdown ms-sm-auto">
<a class="nav-link mb-0" href="#" id="cardShareAction" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-reply-fill flip-horizontal ps-1"></i>Share (3)
</a>
<!-- Card share action dropdown menu -->
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="cardShareAction">
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-envelope fa-fw pe-2"></i>Send via Direct Message</a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-bookmark-check fa-fw pe-2"></i>Bookmark </a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-link fa-fw pe-2"></i>Copy link to post</a>
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-share fa-fw pe-2"></i>Share post via …</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item" href="#"> <i class="bi bi-pencil-square fa-fw pe-2"></i>Share to News Feed</a>
</li>
</ul>
</li>
<!-- Card share action END -->
</ul>
</div>
<!-- Card body END -->
<!-- Card footer START -->
<div class="card-footer border-0 pt-0">
<!-- Load more comments -->
<a href="#!" role="button" class="btn btn-link btn-link-loader btn-sm text-secondary d-flex align-items-center" data-bs-toggle="button" aria-pressed="true">
<div class="spinner-dots me-2">
<span class="spinner-dot"></span>
<span class="spinner-dot"></span>
<span class="spinner-dot"></span>
</div>
Load more comments
</a>
</div>
<!-- Card footer END -->
</div>
<!-- Card feed item END -->
</div>