javascript - helmet - En reactJS, ¿cómo copiar texto al portapapeles?
react title (10)
¿Por qué no utilizar solo el método de recopilación de eventos clipboardData
e.clipboardData.setData(type, content)
?
En mi opinión, es el método más directo para lograr empujar algo dentro del portapapeles, mira esto (lo he usado para modificar datos mientras se copian las acciones nativas):
...
handleCopy = (e) => {
e.preventDefault();
e.clipboardData.setData(''text/plain'', ''Hello, world!'');
}
render = () =>
<Component
onCopy={this.handleCopy}
/>
Seguí ese camino: https://developer.mozilla.org/en-US/docs/Web/Events/copy
¡Salud!
EDITAR: para fines de prueba, he agregado codepen: https://codepen.io/dprzygodzki/pen/ZaJMKb
Estoy usando ReactJS y cuando un usuario hace clic en un enlace, quiero copiar algo de texto en el portapapeles.
Estoy usando Chrome 52 y no necesito admitir ningún otro navegador.
No puedo ver por qué este código no da como resultado que los datos se copien en el portapapeles. (el origen del fragmento de código es de una publicación de Reddit).
¿Estoy haciendo esto mal? ¿Alguien puede sugerir que hay una forma "correcta" de implementar la copia al portapapeles usando reactjs?
copyToClipboard = (text) => {
console.log(''text'', text)
var textField = document.createElement(''textarea'')
textField.innerText = text
document.body.appendChild(textField)
textField.select()
document.execCommand(''copy'')
textField.remove()
}
Aquí está mi código:
import React from ''react''
class CopyToClipboard extends React.Component {
textArea: any
copyClipBoard = () => {
this.textArea.select()
document.execCommand(''copy'')
}
render() {
return (
<>
<input style={{display: ''none''}} value="TEXT TO COPY!!" type="text" ref={(textarea) => this.textArea = textarea} />
<div onClick={this.copyClipBoard}>
CLICK
</div>
</>
)
}
}
export default CopyToClipboard
Definitivamente deberías considerar usar un paquete como @Shubham anterior, es aconsejable, pero creé un codepen funcional basado en lo que describiste: http://codepen.io/dtschust/pen/WGwdVN?editors=1111 . Funciona en mi navegador en Chrome, tal vez puedas ver si hay algo que hice allí que te perdiste, o si hay alguna complejidad extendida en tu aplicación que impide que esto funcione.
onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
La forma más sencilla será usar el paquete npm
react-copy-to-clipboard
.
Puedes instalarlo con el siguiente comando
npm install --save react react-copy-to-clipboard
Úselo de la siguiente manera.
const App = React.createClass({
getInitialState() {
return {value: '''', copied: false};
},
onChange({target: {value}}) {
this.setState({value, copied: false});
},
onCopy() {
this.setState({copied: true});
},
render() {
return (
<div>
<input value={this.state.value} size={10} onChange={this.onChange} />
<CopyToClipboard text={this.state.value} onCopy={this.onCopy}>
<button>Copy</button>
</CopyToClipboard>
<div>
{this.state.copied ? <span >Copied.</span> : null}
</div>
<br />
<input type="text" />
</div>
);
}
});
ReactDOM.render(<App />, document.getElementById(''container''));
Se proporciona una explicación detallada en el siguiente enlace.
https://www.npmjs.com/package/react-copy-to-clipboard
Aquí hay un fiddle corriendo.
Para aquellas personas que están tratando de seleccionar desde el DIV en lugar del campo de texto, aquí está el código. El código se explica por sí mismo, pero comente aquí si desea más información:
import React from ''react'';
....
//set ref to your div
setRef = (ref) => {
// debugger; //eslint-disable-line
this.dialogRef = ref;
};
createMarkeup = content => ({
__html: content,
});
//following function select and copy data to the clipboard from the selected Div.
//Please note that it is only tested in chrome but compatibility for other browsers can be easily done
copyDataToClipboard = () => {
try {
const range = document.createRange();
const selection = window.getSelection();
range.selectNodeContents(this.dialogRef);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand(''copy'');
this.showNotification(''Macro copied successfully.'', ''info'');
this.props.closeMacroWindow();
} catch (err) {
// console.log(err); //eslint-disable-line
//alert(''Macro copy failed.'');
}
};
render() {
return (
<div
id="macroDiv"
ref={(el) => {
this.dialogRef = el;
}}
// className={classes.paper}
dangerouslySetInnerHTML={this.createMarkeup(this.props.content)}
/>
);
}
Personalmente, no veo la necesidad de una biblioteca para esto. Mirando http://caniuse.com/#feat=clipboard ahora es bastante compatible, sin embargo, aún puede hacer cosas como verificar para ver si la funcionalidad existe en el cliente actual y simplemente ocultar el botón de copia si no es así.
import React from ''react'';
class CopyExample extends React.Component {
constructor(props) {
super(props);
this.state = { copySuccess: '''' }
}
copyToClipboard = (e) => {
this.textArea.select();
document.execCommand(''copy'');
// This is just personal preference.
// I prefer to not show the the whole text area selected.
e.target.focus();
this.setState({ copySuccess: ''Copied!'' });
};
render() {
return (
<div>
{
/* Logical shortcut for only displaying the
button if the copy command exists */
document.queryCommandSupported(''copy'') &&
<div>
<button onClick={this.copyToClipboard}>Copy</button>
{this.state.copySuccess}
</div>
}
<form>
<textarea
ref={(textarea) => this.textArea = textarea}
value=''Some text to copy''
/>
</form>
</div>
);
}
}
export default CopyExample;
Actualización: Reescrito usando React Hooks en React 16.7.0-alpha.0
import React, { useRef, useState } from ''react'';
export default function CopyExample() {
const [copySuccess, setCopySuccess] = useState('''');
const textAreaRef = useRef(null);
function copyToClipboard(e) {
textAreaRef.current.select();
document.execCommand(''copy'');
// This is just personal preference.
// I prefer to not show the the whole text area selected.
e.target.focus();
setCopySuccess(''Copied!'');
};
return (
<div>
{
/* Logical shortcut for only displaying the
button if the copy command exists */
document.queryCommandSupported(''copy'') &&
<div>
<button onClick={copyToClipboard}>Copy</button>
{copySuccess}
</div>
}
<form>
<textarea
ref={textAreaRef}
value=''Some text to copy''
/>
</form>
</div>
);
}
Su código debería funcionar perfectamente, lo uso de la misma manera. Solo asegúrese de que si el evento click se dispara desde una pantalla emergente como un modal de arranque o algo así, el elemento creado debe estar dentro de ese modal, de lo contrario no se copiará. Siempre puede dar la identificación de un elemento dentro de ese modal (como un segundo parámetro) y recuperarlo con getElementById, luego agregar el elemento recién creado a ese en lugar del documento. Algo como esto:
copyToClipboard = (text, elementId) => {
const textField = document.createElement(''textarea'');
textField.innerText = text;
const parentElement = document.getElementById(elementId);
parentElement.appendChild(textField);
textField.select();
document.execCommand(''copy'');
parentElement.removeChild(textField);
}
Tomé un enfoque muy similar al de algunos de los anteriores, pero creo que lo hice un poco más concreto. Aquí, un componente principal pasará la url (o el texto que desee) como accesorio.
import * as React from ''react''
export const CopyButton = ({ url }: any) => {
const copyToClipboard = () => {
const textField = document.createElement(''textarea'');
textField.innerText = url;
document.body.appendChild(textField);
textField.select();
document.execCommand(''copy'');
textField.remove();
};
return (
<button onClick={copyToClipboard}>
Copy
</button>
);
};
Use esta sencilla función onClick en línea en un botón si desea escribir datos mediante programación en el portapapeles.
// html
<html>
<body>
<div id="container">
</div>
</body>
</html>
// js
const Hello = React.createClass({
copyToClipboard: () => {
var textField = document.createElement(''textarea'')
textField.innerText = ''foo bar baz''
document.body.appendChild(textField)
textField.select()
document.execCommand(''copy'')
textField.remove()
},
render: function () {
return (
<h1 onClick={this.copyToClipboard}>Click to copy some text</h1>
)
}
})
ReactDOM.render(
<Hello/>,
document.getElementById(''container''))
import React, { Component } from ''react'';
export default class CopyTextOnClick extends Component {
copyText = () => {
this.refs.input.select();
document.execCommand(''copy'');
return false;
}
render () {
const { text } = this.state;
return (
<button onClick={ this.copyText }>
{ text }
<input
ref="input"
type="text"
defaultValue={ text }
style={{ position: ''fixed'', top: ''-1000px'' }} />
</button>
)
}
}