Comment écouter un événement de changement pour un contentEditable
contrôle basé sur?
var Number = React.createClass({
render: function() {
return <div>
<span contentEditable={true} onChange={this.onChange}>
{this.state.value}
</span>
=
{this.state.value}
</div>;
},
onChange: function(v) {
// Doesn't fire :(
console.log('changed', v);
},
getInitialState: function() {
return {value: '123'}
}
});
React.renderComponent(<Number />, document.body);
initialValue
enstate
et l' utiliser dansrender
, mais je ne laisse pas React jour davantage.contentEditable
en changeant mon approche - au lieu d'unspan
ouparagraph
, j'ai utilisé uninput
avec sonreadonly
attribut.Réponses:
Edit: Voir la réponse de Sébastien Lorber qui corrige un bogue dans mon implémentation.
Utilisez l'événement onInput et éventuellement onBlur comme solution de secours. Vous souhaiterez peut-être enregistrer le contenu précédent pour empêcher l'envoi d'événements supplémentaires.
J'aurais personnellement ceci comme fonction de rendu.
jsbin
Qui utilise ce simple wrapper autour de contentEditable.
la source
this.setState({html: "something not in the editable div"}})
this.getDOMNode().innerHTML
enshouldComponentUpdate
est pas très optimisé droitstate.html
la dernière valeur "connue", React ne mettra pas à jour le DOM car le nouveau code HTML est exactement le même en ce qui concerne React (même si le DOM réel est différent). Voir jsfiddle . Je n'ai pas trouvé de bonne solution pour cela, toutes les idées sont donc les bienvenues.shouldComponentUpdate
doit être pur (ne pas avoir d'effets secondaires).Modifier 2015
Quelqu'un a réalisé un projet sur NPM avec ma solution: https://github.com/lovasoa/react-contenteditable
Edit 06/2016: Je viens de rencontrer un nouveau problème qui se produit lorsque le navigateur essaie de "reformater" le html que vous venez de lui donner, conduisant à un re-rendu des composants. Voir
Edit 07/2016: voici mon contenu de production Implémentation modifiable. Il propose des options supplémentaires
react-contenteditable
que vous pourriez souhaiter, notamment:Résumé:
La solution de FakeRainBrigand a très bien fonctionné pour moi pendant un certain temps jusqu'à ce que j'aie de nouveaux problèmes. ContentEditables est pénible, et n'est pas vraiment facile à gérer avec React ...
Ce JSFiddle illustre le problème.
Comme vous pouvez le voir, lorsque vous tapez des caractères et cliquez sur
Clear
, le contenu n'est pas effacé. C'est parce que nous essayons de réinitialiser le contenteditable à la dernière valeur de dom virtuelle connue.Il semble donc que:
shouldComponentUpdate
éviter les sauts de position du curseurshouldComponentUpdate
cette méthode.Vous avez donc besoin d'une ligne supplémentaire pour que chaque fois que
shouldComponentUpdate
retourne oui, vous soyez sûr que le contenu DOM est réellement mis à jour.Donc la version ici ajoute un
componentDidUpdate
et devient:Le dom virtuel reste obsolète, et ce n'est peut-être pas le code le plus efficace, mais au moins ça marche :) Mon bogue est résolu
Détails:
1) Si vous mettez shouldComponentUpdate pour éviter les sauts de curseur, alors les contenteditable ne sont jamais renvoyés (au moins sur les frappes)
2) Si le composant ne se rend jamais sur un coup de touche, React conserve un dom virtuel obsolète pour ce contenu modifiable.
3) Si React conserve une version obsolète du contenteditable dans son arborescence de dom virtuel, alors si vous essayez de réinitialiser le contenteditable à la valeur obsolète dans le dom virtuel, alors pendant la différence de dom virtuel, React calculera qu'il n'y a pas de changement dans postulez au DOM!
Cela se produit principalement lorsque:
la source
{...this.props}
pour que le client puisse personnaliser ce comportement de l'extérieurshouldComponentUpdate
code empêche les sauts d'insertion?C'est la solution la plus simple qui a fonctionné pour moi.
la source
onInput
comme indiqué dans l'exemple.Ce n'est probablement pas exactement la réponse que vous recherchez, mais après avoir lutté avec moi-même et avoir des problèmes avec les réponses suggérées, j'ai décidé de la rendre incontrôlée à la place.
Quand
editable
prop estfalse
, j'utilisetext
prop tel quel, mais quand c'est le castrue
, je passe en mode d'édition dans lequeltext
n'a aucun effet (mais au moins le navigateur ne panique pas). Pendant ce tempsonChange
sont tirés par le contrôle. Enfin, lorsque jeeditable
reviens àfalse
, il remplit le HTML avec tout ce qui a été passétext
:la source
shouldComponentUpdate
si facilement, même si cela ne me sauve plus des sauts de curseur. Enfin, j'ai des:empty:before
espaces réservés de pseudo-éléments CSS mais cetteshouldComponentUpdate
implémentation a empêché FF et Safari de nettoyer le champ lorsqu'il est effacé par l'utilisateur. Il m'a fallu 5 heures pour réaliser que je peux éviter tous ces problèmes avec une CE incontrôlée.editable
dansUncontrolledContentEditable
. Pouvez-vous fournir un exemple exécutable?editable
de l'extérieur. Pensez à un champ qui peut être édité en ligne lorsque l'utilisateur appuie sur «Modifier» et devrait être à nouveau en lecture seule lorsque l'utilisateur appuie sur «Enregistrer» ou «Annuler». Donc quand il est en lecture seule, j'utilise des accessoires, mais j'arrête de les regarder chaque fois que j'entre en «mode édition» et je ne regarde à nouveau les accessoires que lorsque je le quitte.escapeTextForBrowser
pourescapeTextContentForBrowser
.Puisque lorsque la modification est terminée, le focus de l'élément est toujours perdu, vous pouvez simplement utiliser le hook onBlur.
la source
Je suggère d'utiliser un mutationObserver pour ce faire. Cela vous donne beaucoup plus de contrôle sur ce qui se passe. Il vous donne également plus de détails sur la façon dont la navigation interprète toutes les frappes
Ici dans TypeScript
la source
Voici un composant qui en incorpore une grande partie par lovasoa: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
Il cale l'événement dans le emitChange
J'utilise une approche similaire avec succès
la source