I have a ESP32 configured as webserver. I have multiple webpages, that I include as files
for example index.h
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
some divs here....
</html>
)=====";
The content of this page are div's forming a table-like structure.
In my program I have 2 variables numrows
and numtables
that define how many tables i have to show and how many rows each table has. All the id's in there should have the ID adapted accordingly.. For example the first div of the second table could be id="t2d1"
.
Question is: having declared the webpage in a external file like above, how can I dynamically change the contetn before I display the page to the user?
You should post a Minimal, Reproducible Example to get detailed advice. Otherwise we can only guess what's your framework, language, web server etc.
Depends on how your web server works. If it's simple and wants to you to give it the entire page at once, you'll have to allocate a chunk of RAM (e.g. dynamically from heap, or perhaps during compile-time from the data section) and generate the web page in there before handing it to the server.
In extremely simple cases you can just snprintf()
the entire page and hand it over:
const size_t MAX_PAGE_LEN = 128;
const char template[] = "<html><head><title> %s </title></head><body> %s </body></html>";
char* webDoc = (char*) malloc(MAX_PAGE_LEN);
const int len = snprintf(webDoc, MAX_PAGE_LEN, template, "My Title", "My Body");
assert(len > 0 && len < MAX_PAGE_LEN);
// Pass memory in "webDoc" to web server
// webserver.serve(webDoc, len);
free(webDoc);
In more complex cases - such as tables with dynamic size and content - you'd end up writing more complex code (e.g. loop over tables and their rows), but the basic idea remains the same. You have to generate the entire document into a buffer, then pass that to the web server (assuming that's how it works). You might want to create a little library to generate common HTML structures, or find a simple template library to help with code reuse. Take care to allocate enough memory for storing the final document.
For example, I'd use the C++ string streams. They rely heavily on allocating and re-allocating memory from heap which should be mostly OK on the ESP32 - as long as you use common sense. Don't take too much, pre-allocate the amount you expect to use, etc.
#include <iostream>
#include <sstream>
std::ostringstream webDoc;
webDoc << "<html><body>";
for (unsigned table = 0; table < numtables; table++) {
webDoc << "<table>";
for (unsigned row = 0; row < numrows; row++) {
webDoc << "<tr>";
webDoc << "<td>some data</td>";
webDoc << "</tr>";
}
webDoc << "</table>";
}
webDoc << "</body></html>";
// Pass memory in "webDoc" to web server, not optimal as string gets copied
// webserver.serve(webDoc.str().c_str(), webDoc.str().len());
If your web server does not demand the entire document up front, then perhaps you can feed it chunks of it at a time. In such case you'd get away with less memory usage because you could prepare a single row of the table, tell the web server to send it; then prepare the next row.