I'm calling an api with Kotlin and Ktor to get a book in return as json response. From this response I want to load the book cover in my frontend Freimarker .ftl file. I'm doing this call in javascript and write it to html. When I'm calling the function like in my code shown, only the first element in the list get the book cover. The rest is empty. The javascript is executed as inline code in html. I was excepting this function will be called for every new item in the list.
So what can I do to load the image for every element in my list?
index.ftl:
<#-- @ftlvariable name="books" type="kotlin.collections.List<com.nw.models.Book>" -->
<#import "_layout.ftl" as layout />
<@layout.header>
<#list books?reverse as book>
<div >
<hr>
<div >
<div style="width: 18rem;">
<img id="img-book" src="https://via.placeholder.com/128x209.png">
<div >
<h5 >${book.title}</h5>
<p >${book.author}</p>
<input type="hidden" id="img-url" name="imageUrl" placeholder="${book.imageUrl}">
<script type="text/javascript">
(function() {
let a1 = document.getElementById("img-url").getAttribute("placeholder");
const image = document.getElementById("img-book");
image.src = a1;
})();
</script>
<a href="/books/${book.id}" >Go to Book</a>
</div>
</div>
</div>
</div>
</#list>
<hr>
<p>
<a href="/books/new">Create book</a>
</p>
</@layout.header>
CodePudding user response:
With the current DOM scripting approach the OP has to assure that the html render process actually creates a unique id
value for each book item, thus img-url
is not a valid id
value for each book item. The same btw applies to each image element's img-book
id
value. And the placeholder
attribute is not to be abused as data storage; the correct way is the usage of a custom data-*
attribute.
One very easily could even implement an approach which is entirely free of id
attributes and hidden input fields by just using both data related features the custom data-*
attribute and the element's related dataset
property.
<#-- @ftlvariable name="books" type="kotlin.collections.List<com.nw.models.Book>" -->
<#import "_layout.ftl" as layout />
<@layout.header>
<#list books?reverse as book>
<div >
<hr>
<div >
<div style="width: 18rem;">
<img data-book-cover-src="${book.imageUrl}" src="https://via.placeholder.com/128x209.png">
<div >
<h5 >${book.title}</h5>
<p >${book.author}</p>
<a href="/books/${book.id}" >Go to Book</a>
</div>
</div>
</div>
</div>
</#list>
<script type="text/javascript">
document
.querySelectorAll('img[data-book-cover-src]')
.forEach(elmNode =>
elmNode.src = elmNode.dataset.bookCoverSrc
);
</script>
<hr>
<p>
<a href="/books/new">Create book</a>
</p>
</@layout.header>