2017-06-08 5 views
1

Existe-t-il un moyen simple d'exécuter un Cmd après la mise à jour de la vue? En particulier, j'essaie de repositionner le curseur dans un textarea sur des touches spécifiques (comme la touche d'entrée) en cours de pression. Dans ma fonction update je:L'appel d'un port après la vue est mis à jour dans Elm

case keyboardEvent.key of 
    "Enter" -> 
     (modelAfterEnterPressed model keyboardEvent.selectionStart, setCursor model.cursor) 
    "Tab" -> 
     .... 

Mon setCursor port est appelé et le code JavaScript correspondant appelle la fonction de setSelectionRangetextarea correctement. Et puis Elm appelle ma fonction view qui met à jour le contenu de textarea. Malheureusement, cela efface la position de mon curseur.

J'ai besoin que le contenu de textarea soit mis à jour avant en appelant textarea.setSelectionRange() dans mon port JavaScript. Tout moyen de le faire sans recourir à setTimeout qui ne fonctionne pas toujours et peut causer des éclairs dans le délai imparti?

Répondre

0

La manière standard de faire ceci est de déclencher une commande qui revient à la coche suivante - par ex. Date.now - puis déclenchez la commande de port à partir de ce message. Cela garantit que la fonction d'affichage aura été exécutée et que votre zone de texte est présente.

Une alternative qui semble fonctionner aussi bien dans mon expérience, est de remplacer un setTimeout (avec un intervalle arbitraire) avec un requestAnimationFrame:

elm.ports.selectText.subscribe(() => { 
    requestAnimationFrame(() => { 
    var textarea = document.querySelector(...); 
    textarea.setSelectionRange(); 
    }); 
}); 

Cela déclenchera après l'view a été rendu aussi.

+0

Elm a en fait une fonction d'abonnement intégrée pour 'requestAnimationFrame()': http://package.elm-lang.org/packages/elm-lang/animation-frame/latest/AnimationFrame. Mon souci était que les clés tapées puissent être enregistrées/traitées entre le premier 'KeyboardEvent' et le cadre d'animation suivant. Cela jetterait tout. –