I am following the steps from Code snippet: create Components without any frontend tooling (no React, Babel, Webpack, etc) to create a html component.
In a folder mycomponent in parent directory I have created two files.
index.html
:
<html>
<body>
<!DOCTYPE html>
<head>
<title>Place Autocomplete Example</title>
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places"></script>
</head>
<body>
<input id="autocomplete" placeholder="write here" />
<br>
<input id="foo" placeholder="write here" style="width: 200px;" />
</body>
<script>
function initAutocomplete() {
var autocomplete = new google.maps.places.Autocomplete(
document.getElementById('autocomplete'),
);
autocomplete.addListener('place_changed', function () {
var place = autocomplete.getPlace();
var latitude = place.geometry.location.lat();
var longitude = place.geometry.location.lng();
sendDataToPython({
value: latitude + "," + longitude,
dataType: "json",
});
});
}
google.maps.event.addDomListener(window, 'load', initAutocomplete);
function sendDataToPython(data) {
sendMessageToStreamlitClient("streamlit:setComponentValue", data);
}
// ----------------------------------------------------
// Just copy/paste these functions as-is:
function sendMessageToStreamlitClient(type, data) {
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 });
}
// ----------------------------------------------------
// Now modify this part of the code to fit your needs:
// Hook things up!
window.addEventListener("message", function (event) {
if (event.data.type !== "streamlit:render") return;
// Access values sent from Python here!
});
init();
// Hack to autoset the iframe height.
window.addEventListener("load", function () {
window.setTimeout(function () {
setFrameHeight(document.documentElement.clientHeight)
}, 0);
});
setFrameHeight(100);
</script>
</body>
</html>
and __init__.py
:
import streamlit.components.v1 as components
mycomponent = components.declare_component(
"mycomponent",
path="./mycomponent"
)
Then in a streamlit page I write the following:
import streamlit as st
from mycomponent import mycomponent
# Use the component
value = mycomponent()
# Display the value
st.write("Received", value)
When I write something in the component field, it generates a autocomplete picklist below the top text field, appearing on top of the below text field that was embedded in the html component and if you select a value it generates the coordinates for that. It is really good but the problem arises from the fact that the picklist is rendered below the st.write("Received", value)
How to make the html component appear on top of streamlit elements and not only on top of html elements within the component?