2017-09-12 9 views
1

J'écris une petite application Scala.Js qui utilise deux gestionnaires d'événements: un pour l'événement onkeyup d'un champ d'entrée et un autre pour l'événement onclick d'un bouton. Les deux gestionnaires d'événements partagent un peu de codage commun, mais dès que j'essaie d'optimiser le codage du gestionnaire d'événements en une seule fonction renvoyant une fonction de gestionnaire d'événements, il compile correctement, mais les événements ne sont plus pris au piège. le navigateur.Gestion des événements Scala.js

Dans le code suivant dans la fonction main, le gestionnaire d'événements pour btn.onclick fonctionne correctement, mais le gestionnaire d'événements pour cityNameInput.onkeyup ne fonctionne plus. Tout ce que j'ai fait était de copier le code assigné directement au gestionnaire d'événements, et le mettre dans une fonction appelée keystrokeHandler qui renvoie un Function1[dom.Event, _]. Cela compile OK, mais l'événement onkeyup n'est plus emprisonné dans le navigateur.

def keystrokeHandler(userInput: String, responseDiv: dom.Element): Function1[dom.Event,_] = 
(e: dom.Event) => { 
    // The city name must be at least 4 characters long 
    if (userInput.length > 3) { 
    responseDiv.innerHTML = "" 

    val xhr = buildXhrRequest(userInput, searchEndpoint) 

    xhr.onload = (e: dom.Event) => { 
     val data: js.Dynamic = js.JSON.parse(xhr.responseText) 

     // Can any cities be found? 
     if (data.count == 0) 
     // Nope, so show error message 
     responseDiv.appendChild(p(s"Cannot find any city names starting with ${userInput}").render) 
     else { 
     // Build a list of weather reports 
     buildSearchList(data, responseDiv) 
     } 
    } 

    // Send XHR request to OpenWeather 
    xhr.send() 
    } 
} 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Main program 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
@JSExport 
def main(container: dom.html.Div): Unit = { 
    container.innerHTML = "" 

    val cityNameInput = input.render 
    val btn   = button.render 
    val weatherDiv = div.render 

    cityNameInput.defaultValue = owmQueryParams.get("q").get 
    btn.textContent   = "Go" 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Button onclick event handler 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    btn.onclick = (e: dom.Event) => { 
    if (cityNameInput.value.length > 3) { 
     weatherDiv.innerHTML = "" 

     val xhr = buildXhrRequest(cityNameInput.value, weatherEndpoint) 

     xhr.onload = (e: dom.Event) => { 
     val data = js.JSON.parse(xhr.responseText) 

     // Can the city be found? 
     if (data.cod == "404") 
     // Nope, so show error message 
      weatherDiv.appendChild(p(s"City ${cityNameInput.value} not found").render) 
     else { 
      // So first add the div containing both the weather information 
      // and the empty div that will hold the slippy map. 
      // This is needed because Leaflet writes the map information to an 
      // existing DOM element 
      val report = new WeatherReportBuilder(data) 
      weatherDiv.appendChild(buildWeatherReport(report, 0)) 

      buildSlippyMap("mapDiv0", report) 
     } 
     } 

     // Send XHR request to OpenWeather 
     xhr.send() 
    } 
    } 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Input field onkeyup event handler 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv) 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Write HTML to the screen 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    container.appendChild(
    div(
     h1("Weather Report"), 
     table(
     tr(td("Enter a city name (min 4 characters)"), td(cityNameInput)), 
     tr(td(), td(style := "text-align: right", btn)) 
    ), 
     weatherDiv 
    ).render 
) 
} 

Quel est le problème ici?

La fonction keystrokeHandler doit-elle renvoyer un type de gestionnaire d'événements Scala.Js spécial? Ou s'agit-il d'autre chose?

Merci

Chris W

Répondre

1

Je pense que le problème est ici:

cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv) 

Le gestionnaire d'événements est déclenché, mais le userInput est gelé à cityNameInput.valueau moment où le gestionnaire a été créé, au lieu de varier avec la valeur actuelle de cityNameInput.value. En effet, cette ligne équivaut à

val userInput = cityNameInput.value 
cityNameInput.onkeyup = keystrokeHandler(userInput, weatherDiv) 

qui le rend évident que cityNameInput.value est évaluée uniquement une fois.

Au lieu de cela, vous devez donner lui-même cityNameInput comme paramètre à keystrokeHandler, et l'accès cityNameInput.value dans la fonction anonyme, de sorte qu'il est évalué chaque fois que la fonction (gestionnaire) est appelée.

+0

Ah, c'est tout. Merci –