Una variación de este tutorial: https://leafletjs.com/examples/choropleth/ . Estoy intentando agregar un control de información personalizado.
let info = L.control(); function highlightFeature(e) { ... info.update(layer.feature.properties); } function resetHighlight(e) { ... info.update(); } function updateFunction(tab, props) { this._div.innerHTML = '<h4>US Active Covid-19 Cases </h4>' + (props ? '<b>' + props.name + '</b><br />' + getActive(tab, props.name) + ' cases' : 'Hover over a state'); } info.onAdd = function(map) { this._div = L.DomUtil.create("div", "info"); this.update(); return this._div; } let statedata = fetch(url + stateurl).then(data => data.json()); statedata.then((data) => { info.update = (props) => updateFunction(data, props); let style = (feature) => styleMap(data, feature); info.addTo(mymap); geojson = L.geoJson(statesData, {style : style, onEachFeature: onEachFeature}).addTo(mymap); });
Aquí, mi info.update
es ligeramente diferente de los tutoriales. info.update
y el style
dependen de los datos json a los que solo puedo acceder dentro de la sección asíncrona en la parte inferior. Sin embargo, este código me da el siguiente error: Uncaught (in promise) TypeError: Cannot set property 'innerHTML' of undefined
, refiriéndose a la línea this._div
de updateFunction.
Descubrí que si hago cualquiera de los siguientes
let info = L.control()
y todas mis funciones que dependen de la info
dentro de la promesa oinfo.update
fuera de la promesa, entonces el código funcionará sin errores. Sin embargo, la opción 1 parece horrible y moralmente incorrecta, y la opción 2 requiere que abandone la esperanza de acceder a statedata json. Además, en la opción 2, no entiendo qué diferencia hace declarar info.update
dentro o fuera de la promesa. En particular, ¿por qué declarar info.update dentro de la promesa conduce a un comportamiento indefinido con info._div
y declarar info.update
fuera de la promesa no?
¡Cualquier pista sobre lo que está mal aquí sería muy apreciada!
En el tutorial en el que está trabajando, esto es lo que tienen para info.update
:
info.update = function (props) { this._div.innerHTML = '<h4>US Population Density</h4>' + (props ? '<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>' : 'Hover over a state'); };
En esta función, this
se referirá al objeto de info
. En tu código, refactorizas esto:
function updateFunction(tab, props) { this._div.innerHTML = '<h4>US Active Covid-19 Cases </h4>' + (props ? '<b>' + props.name + '</b><br />' + getActive(tab, props.name) + ' cases' : 'Hover over a state'); } // ... info.update = (props) => updateFunction(data, props);
Mediante el uso de una función de flecha que invoca una función regular, ha cortado efectivamente los lazos entre info
y this
. En su caso, es probable que this
sea por defecto window
, lo que explicaría por qué _div
no está definido.
Para solucionar esto, debe vincular explícitamente this
a info
. Podrías hacer esto:
info.update = (props) => updateFunction.bind(info)(data, props);
O incluso más conciso, simplemente puede vincular this
y el primer argumento, y omitir la función de flecha intermedia por completo:
info.update = updateFunction.bind(info, data);