Following the example shared in Code snippet: create Components without any frontend tooling (no React, Babel, Webpack, etc)
I created a custom component.
<html>
<head>
<script src="./idxdbwrapper.js"></script>
</head>
<body>
<script>
function sendMessageToStreamlitClient(type, data) {
console.log("=============================\n", data, type, "\n=============================");
var outData = Object.assign({
isStreamlitMessage: true,
type: type,
}, data);
window.parent.postMessage(outData, "*");
}
function init() {
sendMessageToStreamlitClient("streamlit:componentReady", {apiVersion: 1});
}
function setFrameHeight(height) {
sendMessageToStreamlitClient("streamlit:setFrameHeight", {height: height});
}
// The `data` argument can be any JSON-serializable value.
function sendDataToPython(data) {
sendMessageToStreamlitClient("streamlit:setComponentValue", data);
}
// ----------------------------------------------------
// Now modify this part of the code to fit your needs:
function sortJsonListByTimestampDesc(jsonList) {
return jsonList.sort((a, b) => {
const timestampA = new Date(a.timestamp);
const timestampB = new Date(b.timestamp);
return timestampB - timestampA;
}).slice(0, 20); // Add .slice(0, 10) to get the top 10
}
let isInitialized = false;
function onDataFromPython(event) {
if (event.data.type !== "streamlit:render") return;
if (!isInitialized) {
isInitialized = true;
params = event.data.args.params;
console.log("params", params);
setTimeout(async function() {
db = await initDb("askgbp", "sessions", 1, "sessionid", "sessionid");
if (params.operation.includes("update")) {
await createRecord(db, "sessions", {"sessionid": params.sessionid, "timestamp": new Date().toISOString()});
let records = await getAllRecords(db, "sessions");
sendDataToPython({
result: sortJsonListByTimestampDesc(records),
dataType: "json",
});
}
}, 2);
}
}
// Hook things up!
window.addEventListener("message", onDataFromPython);
init();
// Hack to autoset the iframe height.
window.addEventListener("load", function() {
window.setTimeout(function() {
setFrameHeight(5)
// setFrameHeight(document.documentElement.clientHeight)
}, 0);
});
// Optionally, if the automatic height computation fails you, give this component a height manually
// by commenting out below:
//setFrameHeight(200);
</script>
</body>
</html>
When I test it using the following code: I am only getting None for result = idxdb_component(params=params)
However, the javascript seems to be getting triggered and doing the job as expected. I am not able to retrieve the list back in streamlit for some reason. Please advise. I am stuck for very long on this.
import uuid, time
import streamlit as st
from datetime import datetime
from idx_db_component.frontend import idxdb_component
def main():
def run_component(params):
value = idxdb_component(key=str(datetime.now().strftime("%H:%M:%S, %d %b %Y")), **params)
return value
def handle_event(value):
st.header('Streamlit')
st.write('Received from component: ', value)
params = {
'operation': 'update',
'sessionid': str(uuid.uuid4()),
'datetime': str(datetime.now().strftime("%H:%M:%S, %d %b %Y"))
}
result = idxdb_component(params=params)
print("===========================================\n", result, "\n===========================================")
if __name__ == '__main__':
main()