Hi I have a problem on code below I can't add a firestore collection to a db, when the setDoc line is executed it doesn't add the document to the collection, and the strange thing is that it doesn't print anything console, I'm using react, even though I use the add doc it does the same thing, the app is already connected to firebase because I logged in so the parameters are correct, what can it be?
FirebaseFile.js
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
var firebaseConfig = {
...
};
// Initialize Firebase
var app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
Another.js
import React, { useRef, useState } from 'react';
import { doc, setDoc,collection } from 'firebase/firestore';
import styled from 'styled-components';
import EmailEditor from '../../../src';
import sample from './sample.json';
import sample2 from './sample2.json';
import sample3 from './sample3.json';
import { db } from '../firebase';
import Checkbox from '#mui/material/Checkbox';
import axios from 'axios';
const label = { inputProps: { 'aria-label': 'Checkbox demo' } };
const Container = styled.div`
display: flex;
flex-direction: column;
position: relative;
height: 100%;
`;
const Bar = styled.div`
flex: 1;
background-color: #000000;
color: #000;
padding: 10px;
display: flex;
max-height: 40px;
h1 {
flex: 1;
font-size: 16px;
text-align: left;
}
button {
flex: 1;
padding: 10px;
margin-left: 10px;
font-size: 14px;
font-weight: bold;
background-color: #000;
color: #fff;
border: 0px;
max-width: 150px;
cursor: pointer;
}
`;
const Example = () => {
const emailEditorRef = useRef(null);
const [titolo, setTitolo] = useState('');
const [newsProfileValue, setNewsProfileSet] = useState('');
const [profileList, setNewsProfileList] = useState([]);
const [premiumValue, setPremium] = useState(false);
const [publicValue, setPublic] = useState(false);
const arr = [];
const saveDesign = () => {
emailEditorRef.current.editor.saveDesign((design) => {
exportData(design);
});
};
const getList = async () => {
try {
//Recupero lo user id
var id = await localStorage.getItem('uid');
console.log(id);
var data = [];
const querySnapshot = await getDocs(collection(db, 'news_profiles'));
querySnapshot.forEach((doc) => {
if (doc.data().about.uid == id) {
data.push({ title: doc.data().about.title, id: doc.id });
arr.push({ doc: doc.data().about.title, id: doc.id });
}
});
} catch (error) {
console.log('Error: ' + error);
}
var options = arr.map((e) => {
return `<option value="${e.id}">${e.doc}</option>`;
});
document.getElementById('selectNumber').innerHTML = options;
setNewsProfileList(data);
};
const exportData = (design) => {
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(design)
)}`;
const link = document.createElement('a');
link.href = jsonString;
link.download = 'data.json';
link.click();
};
const exportHtml = () => {
console.log('Sono in export html');
addElementToFireStoreNews('prova');
emailEditorRef.current.editor.exportHtml((data) => {
const { design, html } = data;
console.log('Sono dentor export');
addElementToFireStoreNews(html);
console.log("Sono dentor l'export");
});
};
const addElementToFireStoreNewsAWS = async (html) => {
var jsonFile;
var templateid = await localStorage.getItem('templateid');
if (templateid == 1) {
jsonFile = sample;
} else if (templateid == 2) {
jsonFile = sample3;
} else {
jsonFile = sample2;
}
//Salvo la newsletter su aws
emailEditorRef.current.editor.exportHtml((data) => {
const { design, html } = data;
var dataValue = {
internal: true,
online: publicValue,
premium: premiumValue,
html: html,
template: jsonFile,
subject: html,
email: uuid,
};
axios
.post(
`https://europe-west3-mindit-newsletter.cloudfunctions.net/newsCreate`,
dataValue
)
.then((res) => {
console.log(res.json());
});
});
};
const addElementToFireStoreNews = async (html) => {
console.log("Sono nell'inserimento del html");
try {
//addElementToFireStoreNewsAWS(html);
var uuid = await localStorage.getItem('uid');
const value = {
aboutNews: {
email: newsProfileValue,
html: html,
internal: true,
photo: '',
title: titolo,
},
date: new Date(),
id: uuid,
measures: {
impression: {
total: 0,
},
views: {
moth: 0,
total: 0,
week: 0,
},
},
public: true,
searchKey: '',
premium: premiumValue,
};
const newCityRef = doc(collection(db, 'news'));
await setDoc(newCityRef, value);
} catch (err) {
console.log('Errore inserimnento: ' + err);
}
};
const onDesignLoad = (data) => {
console.log('onDesignLoad', data);
};
const onLoad = async () => {
getList();
var templateid = await localStorage.getItem('templateid');
if (templateid == 1) {
emailEditorRef.current.editor.loadDesign(sample);
} else if (templateid == 2) {
emailEditorRef.current.editor.loadDesign(sample3);
} else {
emailEditorRef.current.editor.loadDesign(sample2);
}
emailEditorRef.current.editor.addEventListener(
'design:loaded',
onDesignLoad
);
};
const onReady = () => {};
const changeText = (text) => {
setTitolo(text);
};
const clickValue = (e) => {
setNewsProfileSet(e.target.value);
};
const changeValue = () => {
setPremium(!premium);
};
const changeValuePublic = () => {
setPublic(!publicValue);
};
return (
<Container>
<Bar>
<img src="firebase.png" width="100" height="50" />
<label style={{ color: 'white' }}>
<b>Titolo News: </b>
<input
type="text"
name="name"
onChange={(value) => changeText(value.target.value)}
style={{ marginRight: 200 }}
/>
Premium:{' '}
<Checkbox
{...label}
unchecked
onClick={() => changeValue()}
style={{ color: 'white' }}
/>
Online:{' '}
<Checkbox
{...label}
unchecked
onClick={() => changeValuePublic()}
style={{ color: 'white' }}
/>
</label>
<form id="myForm">
<select id="selectNumber" onClick={clickValue}>
<option>Scegli il news profile</option>
</select>
<button onClick={() => saveDesign}> Salva Design </button>
<button onClick={() => addElementToFireStoreNews('prova')}>
{' '}
Salva Articolo{' '}
</button>{' '}
</form>
</Bar>
<React.StrictMode>
<EmailEditor ref={emailEditorRef} onLoad={onLoad} onReady={onReady} />{' '}
</React.StrictMode>{' '}
</Container>
);
};
export default Example;
It seems like you merged two files but you listed this as one file. If that's one file, then you are importing db twice which would be a problem:
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
var firebaseConfig = {
...
};
// Initialize Firebase
var app = initializeApp(firebaseConfig);
export const db = getFirestore(app); <-------- Use this.
import React, { useRef, useState } from 'react';
import { doc, setDoc,collection } from 'firebase/firestore';
import styled from 'styled-components';
import EmailEditor from '../../../src';
import sample from './sample.json';
import sample2 from './sample2.json';
import sample3 from './sample3.json';
import { db } from '../firebase'; <----- What is this?
Otherwise, if you are having the problem locally, make sure you are starting your local Firestore Emulator or else you'll probably be updating your live Firestore instance.
// detect for development ENV
connectFirestoreEmulator(db, '127.0.0.1', 6060);
Related
I'm using NextJS and Remirror Editor plugin. I get an error that setContent is undefined on the index page where the editor is loaded. I want to add an "external" button after the Component is loaded to exit the text. The component is dynamically externally loaded. I'm really unsure how to make the external button/text change to work.
Index.tsx:
import { NextPage, GetStaticProps } from 'next';
import dynamic from 'next/dynamic';
import { WysiwygEditor } from '#remirror/react-editors/wysiwyg';
import React, { useRef, useEffect } from 'react';
const TextEditor = dynamic( () => import('../text-editor'), { ssr: false } );
import natural from "natural";
export interface EditorRef {
setContent: (content: any) => void;
}
type Props = {
aaa:string
bbb:string
}
const Home: NextPage< Props > = (props) => {
//hook call ref to use editor externally
const ref = useRef<EditorRef | null>(null);
const {aaa,bbb} = props;
return (
<>
<ul>
{aaa} </ul>
Next.js Home Page
<TextEditor ref={ref} />
{
useEffect(()=>{
ref.current!.setContent({content: "testing the text has changed"})
},[])}
<button onClick={() => ref.current.setContent({content: "testing the text has changed"})}>Set another text button 2</button>
</>
);
};
var stringWordNet = "";
export const getStaticProps = async ():Promise<GetStaticPropsResult<Props>> => {
var wordnet = new natural.WordNet();
wordnet.lookup('node', function(results) {
stringWordNet = String(results[0].synonyms[1]);
});
return {
props:{
aaa:stringWordNet,
bbb:"bbb"
}
}
};
export default Home;
text-editor.tsx
import 'remirror/styles/all.css';
import { useEffect, useState, forwardRef, Ref, useImperativeHandle, useRef } from 'react';
import { BoldExtension,
ItalicExtension,
selectionPositioner,
UnderlineExtension, MentionAtomExtension } from 'remirror/extensions';
import { cx } from '#remirror/core';
import {
EditorComponent,
FloatingWrapper,
MentionAtomNodeAttributes,
Remirror,
useMentionAtom,
useRemirror, ThemeProvider, useRemirrorContext
} from '#remirror/react';
import { css } from "#emotion/css";
const styles = css`
background-color: white;
color: #101010;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px;
`;
const ALL_USERS = [
{ id: 'wordnetSuggestion1', label: 'NotreSuggestion1' },
{ id: 'wordnetSuggestion2', label: 'NotreSuggestion2' },
{ id: 'wordnetSuggestion3', label: 'NotreSuggestion3' },
{ id: 'wordnetSuggestion4', label: 'NotreSuggestion4' },
{ id: 'wordnetSuggestion5', label: 'NotreSuggestion5' },
];
const MentionSuggestor: React.FC = () => {
return (
<FloatingWrapper positioner={selectionPositioner} placement='bottom-start'>
<div>
{
ALL_USERS.map((option, index) => (
<li> {option.label}</li>
))
}
</div>
</FloatingWrapper>
);
};
const DOC = {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'New content',
},
],
},
],
};
//Start Imperative Handle Here
export interface EditorRef {
setContent: (content: any) => void;
}
const ImperativeHandle = forwardRef((_: unknown, ref: Ref<EditorRef>) => {
const { setContent } = useRemirrorContext({
autoUpdate: true,
});
// Expose content handling to outside
useImperativeHandle(ref, () => ({ setContent }));
return <></>;
});
//Make content to show.
const TextEditor = forwardRef((_: unknown, ref: Ref<EditorRef>) => {
const editorRef = useRef<EditorRef | null>(null);
const { manager, state, getContext } = useRemirror({
extensions: () => [
new MentionAtomExtension()
],
content: '<p>I love Remirror</p>',
selection: 'start',
stringHandler: 'html',
});
return (
<>
<button
onMouseDown={(event) => event.preventDefault()}
onClick={() => editorRef.current!.setContent(DOC)}
></button>
<div className='remirror-theme'>
<Remirror manager={manager} initialContent={state}>
<EditorComponent />
<MentionSuggestor />
<ImperativeHandle ref={editorRef} />
</Remirror>
</div>
</>
);
});
export default TextEditor;
i've been learning vuejs for 2 weeks and i'm stuck a day to this problem when i passing a reactive data to child component using axios
here's the code :
<template>
<div class="wrapper">
<div class="box-container">
<TreeChart
:json="tree"
:class="{ landscape: landscape.length }"
#click-item="clickItem"
/>
</div>
</div>
</template>
<script lang="ts">
import TreeChart from "#/components/TreeChart.vue";
import { defineComponent, ref } from "vue";
import { useRouter } from "vue-router";
import http from "#/common-setup/http";
export default defineComponent({
props: ["treeUid"],
setup(props) {
const landscape = ref([]);
let tree = ref({} as any);
const router = useRouter();
if (
props.treeUid === undefined ||
props.treeUid === null ||
props.treeUid === ""
) {
router.push({ name: "NotFoundResource" });
}
let response = http
.get(`/wv/tree/show/${props.treeUid}`)
.then((response) => {
if (response.data.response.length === 0) {
tree.value = {};
router.push({ name: "emptyTree" });
}
tree.value = response.data.response[0];
})
.catch((err) => {
console.log(err);
})
.then(() => {
console.log("done");
});
function clickItem(item: any) {
console.log(item);
}
return { tree, landscape, clickItem };
},
components: {
TreeChart,
},
});
</script>
<style scoped>
.wrapper {
#apply flex;
flex-direction: row;
#apply relative;
width: 100%;
}
.box-container {
margin: 0 auto;
}
</style>
here is setup api on child component
import { ref, watch, getCurrentInstance } from "vue";
import { TreeTypes } from "#/types/Tree";
export default function treeChart(props?: any) {
let treeData = ref({} as any);
const { ctx: _this }: any = getCurrentInstance();
// console.log(props.json);
watch(
props.json,
(props) => {
let showKey = function (jsonData: any) {
jsonData.extend = jsonData.extend === void 0 ? true : !!jsonData.extend;
// console.log(jsonData);
if (Array.isArray(jsonData.children)) {
jsonData.children.forEach((c: any) => {
showKey(c);
});
}
return jsonData;
};
if (props) {
treeData = showKey(props);
}
},
{ immediate: true }
);
function toggleTree(treeData: any): void {
treeData.extend = !treeData.extend;
_this.$forceUpdate();
}
return { treeData, toggleTree };
}
if i use dummy data not data from axios it will working and it become more weird when in hot reload mode, i tried to console it the data from axios suddenly appear.
is there something wrong how i pass the data with axios to the child component ?
I have a big problem with React TimeLines Package(https://openbase.com/js/react-timelines)
I want something like this photo:
( having 3 P tags with different ClassNames)
but in default case of this package I cant do it!
I think I should use something like createElement and textContent in JS. but I dont know how!
My Codes:
import React, { Component } from "react";
import Timeline from "react-timelines";
import "react-timelines/lib/css/style.css";
import { START_YEAR, NUM_OF_YEARS, NUM_OF_TRACKS } from "./constant";
import { buildTimebar, buildTrack } from "./builder";
import { fill } from "./utils";
const now = new Date("2021-01-01");
const timebar = buildTimebar();
// eslint-disable-next-line no-alert
const clickElement = (element) =>
alert(`Clicked element\n${JSON.stringify(element, null, 2)}`);
class App extends Component {
constructor(props) {
super(props);
const tracksById = fill(NUM_OF_TRACKS).reduce((acc, i) => {
const track = buildTrack(i + 1);
acc[track.id] = track;
return acc;
}, {});
this.state = {
open: false,
zoom: 2,
// eslint-disable-next-line react/no-unused-state
tracksById,
tracks: Object.values(tracksById),
};
}
handleToggleOpen = () => {
this.setState(({ open }) => ({ open: !open }));
};
handleToggleTrackOpen = (track) => {
this.setState((state) => {
const tracksById = {
...state.tracksById,
[track.id]: {
...track,
isOpen: !track.isOpen,
},
};
return {
tracksById,
tracks: Object.values(tracksById),
};
});
};
render() {
const { open, zoom, tracks } = this.state;
const start = new Date(`${START_YEAR}`);
const end = new Date(`${START_YEAR + NUM_OF_YEARS}`);
return (
<div className="app">
<Timeline
scale={{
start,
end,
zoom,
}}
isOpen={open}
toggleOpen={this.handleToggleOpen}
clickElement={clickElement}
timebar={timebar}
tracks={tracks}
now={now}
enableSticky
scrollToNow
/>
</div>
);
}
}
export default App;
builder.js:
export const buildElement = ({ trackId, start, end, i }) => {
const bgColor = nextColor();
const color = colourIsLight(...hexToRgb(bgColor)) ? "#000000" : "#ffffff";
return {
id: `t-${trackId}-el-${i}`,
title: "Bye Title: Hello Type: String",
start,
end,
style: {
backgroundColor: `#${bgColor}`,
color,
borderRadius: "12px",
width: "auto",
height: "120px",
textTransform: "capitalize",
},
};
};
I am trying to make a survey tool with firebase and react and I am implementing a template feature, so now one of the templates is working, when user clicks on create new survey, I have various buttons shown to them like: blank, temp1,temp2,temp3,temp4 based on whatever is clicked a clickhandler is triggered, now how do I update the content of the state based on which template i am getting? below is my code:
<button onClick={props.clicked} className={classes.Board}>
Board Survey
</button>
<button onClick={props.chair} className={classes.Chair}>
Chairperson Survey
</button>
<button onClick={props.member} className={classes.Member}>
Board Member Survey
</button>
And now i use
clicked={this.clickHandler}
The code to fetch survey template:
const fetchSurvey = async () => {
const res = await axios.get(
"/surveys/ckb0kmt3n000e3g5rmjnfw4go/content/questions.json"
);
return res.data;
};
Where "ckb0kmt3n000e3g5rmjnfw4go" is the survey id
const content = {
title: "Your Survey Tite",
subTitle: "Your Survey Description",
creatorDate: new Date(),
lastModified: new Date(),
questions: fetchSurvey().then(questions => {
this.setState(state => ({
...state,
content: {
...state.content,
questions
}
}));
}),
submitting: true
};
this.setState({
_id: newId(),
content: content,
userId: this.props.user_Id
});
}
Now how to do i update the questions key to run different functions based on which templates i choose on the previous page?
ClickHandler Code:
clickHandler = () => {
const newSurvey = { ...this.state };
axios
.put(
"/surveys/" + this.state._id + ".json?auth=" + this.props.token,
newSurvey
)
.then(res => {
this.props.onGetSurveyId(res.data._id);
})
.catch(error => {
console.log(error);
});
};
File1:
import React from "react";
import Button from "#material-ui/core/Button";
import Icon from "#material-ui/core/Icon";
import { makeStyles } from "#material-ui/core/styles";
import classes from "./NewSurvey.module.css";
import { Link } from "react-router-dom";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogTitle from "#material-ui/core/DialogTitle";
import InputLabel from "#material-ui/core/InputLabel";
import Input from "#material-ui/core/Input";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
const NewSurvey = props => {
const [open, setOpen] = React.useState(false);
const [template, setTemplate] = React.useState("");
const handleChange = event => {
setTemplate(Number(event.target.value) || "");
};
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const notify = () =>
toast.info("Creating Survey....Please Wait", {
position: "top-right",
autoClose: 5000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined
});
return (
<div className={classes.CreateSurvey}>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar
newestOnTop
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
<Dialog
disableBackdropClick
disableEscapeKeyDown
open={open}
onClose={handleClose}
className={classes.Dialog}
>
<DialogTitle className={classes.DialogTitle}>
Create New Survey
</DialogTitle>
<h5 className={classes.Info}>
Choose a template or start with a blank survey
</h5>
<DialogContent>
<button
onClick={function(event) {
props.clicked();
notify();
}}
className={classes.Blank}
>
Blank Survey
</button>
<button onClick={props.board} className={classes.Board}>
Board Survey
</button>
<button onClick={props.chair} className={classes.Chair}>
Chairperson Survey
</button>
<button onClick={props.member} className={classes.Member}>
Board Member Survey
</button>
</DialogContent>
<DialogActions>
<button onClick={handleClose} className={classes.CancelButton}>
Cancel
</button>
</DialogActions>
</Dialog>
<button
className={classes.NewSurvey}
onClick={handleClickOpen}
disabled={props.isLoading || props.error}
>
<Icon className={classes.Icon}>add_circle_outline</Icon> Create New
Survey
</button>
</div>
);
};
export default NewSurvey;
File 2:
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import newId from "../../../ulitity/idGenerator";
import axios from "../../../axios-order";
import * as actionTypes from "../../../Store/actions/actionsTypes";
import NewSurveyView from "../../../Components/NewSurvey/NewSurvey";
import { InitQuestions } from "../../../ulitity/constants/Questions";
class NewSurvey extends Component {
state = {
_id: "",
userId: "",
content: {
title: "Your Survey Title",
subTitle: "",
creatorDate: "",
lastModified: ""
}
};
componentDidMount() {
var sampleQuestion;
var questionObj;
sampleQuestion = InitQuestions["SINGLE_LINE_TEXT"]();
questionObj = {
[sampleQuestion._id]: sampleQuestion
};
var orderQuestions;
let questions = [sampleQuestion._id];
orderQuestions = questions.map(questionId => questionObj[questionId]);
const fetchBoardMember = async () => {
const res = await axios.get(
"/surveys/ckb0kmt3n000e3g5rmjnfw4go/content/questions.json"
);
return res.data;
};
const fetchBoard = async () => {
const res = await axios.get(
"/surveys/ckb24goc800013g5r7j8igrk3/content/questions.json"
);
return res.data;
};
const fetchChair = async () => {
const res = await axios.get(
"/surveys/ckb24gt3s00053g5rrf60353r/content/questions.json"
);
return res.data;
};
const content = {
title: "Your Survey Title",
subTitle: "Your Survey Description",
creatorDate: new Date(),
lastModified: new Date(),
questions: fetchBoard().then(questions => {
this.setState(state => ({
...state,
content: {
...state.content,
questions
}
}));
}),
submitting: true
};
this.setState({
_id: newId(),
content: content,
userId: this.props.user_Id
});
}
clickHandler = () => {
const newSurvey = { ...this.state };
axios
.put(
"/surveys/" + this.state._id + ".json?auth=" + this.props.token,
newSurvey
)
.then(res => {
this.props.onGetSurveyId(res.data._id);
})
.catch(error => {
console.log(error);
});
};
render() {
return (
<div>
<NewSurveyView
clicked={this.clickHandler}
board={this.boardHandler}
chair={this.chairHandler}
member={this.memberHandler}
isLoading={this.props.loading}
error={this.props.isError}
/>
</div>
);
}
}
const mapStateToProps = state => {
return {
user_Id: state.auth.userId,
token: state.auth.token,
surveyId: state.surveyEditer.survey.id
};
};
const mapDispatchToProps = dispatch => {
return {
onGetSurveyId: surveyId =>
dispatch({ type: actionTypes.GET_SURVEY_ID, surveyId: surveyId })
};
};
export default withRouter(
connect(mapStateToProps, mapDispatchToProps)(NewSurvey)
);
I am using the React Draft Wysiwyg and I need to insert arbitrary text from one component of my application into the editor component. I am doing this via the clipboard as an intermediary for the transfer from one component to the other. But the document.execCommand('paste') fails.
Does anybody know how to do this?
My sample code is here; the third console log emits false for the paste result.
import React, { Component } from 'react';
import { EditorState, convertToRaw, Modifier } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import styled from 'styled-components';
class EditorConvertToHTML extends Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.onChange = (editorState) => this.setState({editorState});
this.setEditor = (editor) => {
this.editor = editor;
};
this.focusEditor = () => {
if (this.editor) {
this.editor.focusEditor();
console.log("1. Editor has the focus now");
}
};
}
componentDidMount() {
this.focusEditor();
}
onEditorStateChange = (editorState) => {
this.setState({
editorState,
});
};
sendTextToEditor = (text) => {
var input = document.createElement('input');
input.setAttribute('value', text);
document.body.appendChild(input);
input.select();
var result = document.execCommand('copy');
document.body.removeChild(input);
navigator.clipboard.readText()
.then(text => {
this.focusEditor();
console.log('2. Retrieved pasted text from clipboard = ', text);
result = document.execCommand('paste');
console.log("3. Paste command's result = ", result);
})
.catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
return result;
}
render() {
const { editorState } = this.state;
return (
<>
<EditorStyled>
<Editor
ref={this.setEditor}
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={this.onEditorStateChange}
/>
</EditorStyled>
<button type="button" onClick={this.sendTextToEditor.bind(this, 'Sample text to put in editor')}>Copy sample text to editor</button>
</>
);
}
}
export default EditorConvertToHTML;
const EditorStyled = styled.div`
width: ${() => "calc(100% - 40px)"};
min-height: 400px;
margin: 20px;
border: 1px solid black;
`;
Thank you in advance for your help!
Thanks to Rosemarie Robertson's explanations/article # https://dev.to/rose/draft-js-simple-content-manipulation-b7a I got the sample working. Here is the code:
import React, { Component } from 'react';
import { EditorState, Modifier } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import styled from 'styled-components';
// Following sample is based the article https://dev.to/rose/draft-js-simple-content-manipulation-b7a
class EditorConvertToHTML extends Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
}
componentDidMount() {
this.focusEditor();
}
setEditor = (editor) => {
this.editor = editor;
};
focusEditor = () => {
if (this.editor) {
this.editor.focusEditor();
console.log("1. Editor has the focus now");
}
};
onEditorStateChange = (editorState) => {
this.setState({
editorState,
});
};
sendTextToEditor = (text) => {
this.setState({editorState: this.insertText(text, this.state.editorState)});
this.focusEditor();
}
insertText = (text, editorState) => {
const currentContent = editorState.getCurrentContent(),
currentSelection = editorState.getSelection();
const newContent = Modifier.replaceText(
currentContent,
currentSelection,
text
);
const newEditorState = EditorState.push(editorState, newContent, 'insert-characters');
return EditorState.forceSelection(newEditorState, newContent.getSelectionAfter());
}
render() {
const { editorState } = this.state;
return (
<>
<EditorStyled>
<Editor
ref={this.setEditor}
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={this.onEditorStateChange}
/>
</EditorStyled>
<button type="button" onClick={this.sendTextToEditor.bind(this, 'Sample text to put in editor')}>Copy sample text to editor</button>
</>
);
}
}
export default EditorConvertToHTML;
const EditorStyled = styled.div`
width: ${() => "calc(100% - 40px)"};
min-height: 400px;
margin: 20px;
border: 1px solid black;
`;