I am using react-quill and I wan't to know how to select an image after being inserted into the editor and how to get the delted image url after being delted.
Here is my Editor Component
import React,{useState} from 'react'
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
const modules = {
toolbar:{
container: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline','strike', 'blockquote'],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
['link', 'image'],
['clean']
],
handlers:{
'image': async function(){
const editor=this.quill
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.addEventListener('change',(e)=>{
const url=awiat uploadFile(e.target.files[0))
const range = editor.getSelection(true);
editor.insertEmbed(range.index, 'image', url;
editor.setSelection(range.index + 1)
})
}
}
}
}
const formats = [
'header', 'font', 'size',
'bold', 'italic', 'underline', 'strike', 'blockquote',
'list', 'bullet', 'indent',
'link', 'image', 'color',
]
function Editor() {
const [editorData,setEditorData]=useState(" ")
const handleChange=(value)=>{
setEditorData(value)
}
return (
<div>
<ReactQuill formats={formats} modules={modules} value={editorData}
onChange={(data)=>handleChange(data)} />
</div>
)
}
export default Editor
So, how can i select a image inside the editor after being inserted and get the url after being deleted from the editor.
First, you should store your uploaded image URL inside an array like:
const [addresses, setAddresses] = useState([])
addresses.push(url)
Then when you submit the form, check if these addresses exist in your editor content save them, else any of them not exists delete it.
addresses.map(async (a) => {
if (!yourEditorValue.includes(a)) {
/* here you can add your method according to your backend, I am
using strapi */
const deletePhoto = await axios.delete(
`${yourServerUrl}/upload/files/${id}`,
{
//this one is not necessary if you don't need
headers: {
Authorization: `Bearer ${yourToken}`,
},
},
)
}
return true
})
Related
I have some issues with dynamic import of the component in my NextJs app. I'm trying to import Froala text editor and it's supported for React. But, when I try to import it, I have errors that window is not defined, so I'm importing it with next/dynamic.
So the problem is, this editor should not reload on every change on page. Whatever I do, ex. change state, it will rerender the component. It's only blinking, but still cannot show like so to the client. Is there any other way I could use component and not "blink"?
Here is my component:
import FroalaEditor from 'react-froala-wysiwyg';
const Froala = (props: {model: any, onChanged: any}) => {
return (
<div>
<FroalaEditor model={props.model} onModelChange={props.onChanged} config={{
toolbarButtons: ['fullscreen', 'bold', 'italic', 'textColor', 'backgroundColor', 'underline', 'strikeThrough', 'fontFamily', 'fontSize', 'color', 'inlineClass', 'inlineStyle', 'paragraphStyle', 'paragraphFormat', 'align', 'formatOL', 'formatUL', 'outdent', 'indent', 'quote', 'insertLink', 'insertImage', 'insertVideo', 'embedly', 'insertFile', 'insertTable', 'emoticons', 'fontAwesome', 'specialCharacters', 'insertHR', 'selectAll', 'clearFormatting', 'print', 'getPDF', 'spellChecker', 'help', 'html', 'undo', 'redo'],
toolbarButtonsXS: ['bold', 'italic', 'fontFamily', 'fontSize', 'undo', 'redo'],
placeholderText: 'Edit Your Content Here!',
charCounterCount: false,
theme: 'dark',
imageUploadParam: 'image_param',
fileUploadMethod: 'POST',
fileUploadURL: 'http://127.0.0.1:8000/upload_file',
// Set the image upload URL.
imageUploadMethod: 'POST',
imageUploadURL: 'http://127.0.0.1:8000/api/upload/image',
// Set request type.
// Set max image size to 5MB.
imageMaxSize: 5 * 1024 * 1024,
// Allow to upload PNG and JPG.
imageAllowedTypes: ['jpeg', 'jpg', 'png'],
}}/>
</div>
)
}
export default Froala
And importing to other components would be:
const FroalaEditor = dynamic(() => import('../Froala'), {
ssr: false
});
It's not important what I change on the page... dispatch, state, or whatever that can cause rerendering, it will blink. How can I prevent this?
Btw, if component is directly imported, it's giving an error of undefined window!
In laravel 9 with Inertiajs/vuejs 3 I need to add table into vueup/vue-quill editor
and looking at this article
https://vueup.github.io/vue-quill/guide/modules.html#example
Adding QuillBetterTable support into my app:
<quill-editor
:options="editorOptions"
:modules="modules"
theme="snow"
:disabled="false"
v-model:content="descriptionFormEditor.description"
text-change="textChangeDescription"
editorChange="editorChangeDescription"
contentType="html"
#blur="onEditorBlur($event)"
#focus="onEditorFocus($event)"
#ready="onEditorReady($event)"
#textChange="onTextChange($event)"
>{{ descriptionFormEditor.description }}
</quill-editor>
...
import { QuillEditor } from '#vueup/vue-quill'
import '#vueup/vue-quill/dist/vue-quill.snow.css';
import QuillBetterTable from 'quill-better-table' // https://github.com/soccerloway/quill-better-table
...
let editorOptions = ref(
[['better-table', 'bold', 'italic'], ['link', 'image']]
)
let modules = ref({
table: false, // disable table module
'better-table': {
operationMenu: {
items: {
unmergeCells: {
text: 'Another unmerge cells name'
}
},
color: {
colors: ['#fff', 'red', 'rgb(0, 0, 0)'], // colors in operationMenu
text: 'Background Colors' // subtitle
}
}
},
keyboard: {
bindings: QuillBetterTable.keyboardBindings
}
}
)
...
...
return
editorOptions,
modules,
...
But I got next error : https://prnt.sc/EIKGal7poJyT
Any hints what is it and how it can be fixed ?
Thanks!
I have an api that returns JSON with object array {component_name: string, component_data: any}. Based on this response render react page using function with switch-case by component_name and pass data to component in this case. I have many componets and this switch is very large. Can it be solved differently?
code snippet eg.
import Header from "./Header";
import Link from "./Link";
import Image from "./Image";
const pageComponents = (pageJson) => pageJson.map(p => {
switch(p.component_name) {
case: 'header': {
return <Header content={p.component_data.text} />
case: 'link': {
return <Link content={p.component_data.text} href={p.component_data.src} />
case: 'image': {
return <Image src={p.component_data.src} alt={p.component_data.alt} />
}
}
});
const EgPage = () => {
const pageJSON = [
{component_name: 'header', component_data: {text: 'Heder text 1'}},
{component_name: 'link', component_data: {text: 'Heder text 2', src: 'www.test.com'}},
{component_name: 'image', component_data: {src: 'www.test.img/1.jpg', alt: 'Test img'},
{component_name: 'header', component_data: {text: 'Heder text 2'},
]
return <div>{pageComponents(pageJSON)}</div>
}
I use draftJS to edit text in my project, and at the moment I'm faced with such a problem that if you include a list with dots or numbers in an empty editor, then it cannot be deleted with the backspace key
my editor
```<Editor
editorState={description}
toolbarStyle={editorStyles.toolbarStyle}
editorStyle={editorStyles.editorStyle}
onEditorStateChange={onChangeDescription}
placeholder={placeholder}
toolbar={toolbar}
/>```
I just study draft.js. you can handle the key command by RichUtils.handleKeyCommand.
The code below is that i create a function handleKeyCommandEn.then it can handle backspace to remove list
import { EditorState, convertToRaw, ContentState,RichUtils } from "draft-js";
...
const [editorStateEn, setEditorStateEn] = useState<EditorState>(EditorState.createEmpty());
const handleKeyCommandEn = (command) => {
const newState = RichUtils.handleKeyCommand(editorStateEn, command);
if (newState) {
setEditorStateEn(newState);
return true;
}
return false;
};
...
<Editor
editorState={editorStateEn}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={setEditorStateEn}
toolbar={{
options:['inline','blockType', 'fontSize', 'fontFamily', 'list', 'textAlign', 'remove', 'history'],
textAlign: { inDropdown: true },
inline :{options:['bold', 'italic', 'underline', 'strikethrough','superscript','subscript']}
}}
localization={{
locale: 'en',
}}
stripPastedStyles={true} // disable paste style
handleKeyCommand={handleKeyCommandEn}
placeholder={intl.formatMessage({ id: "editorPlaceholder" })}
/>
I'm a beginner on Gatsby. I try to display a batch of images in grid from a specific folder. I find a script to do that, but that's catch all pics from my data folder and my purpose is target a specific one. I try a script but that's don't work with allImageSharp when I try to filter this one allImageSharp(filter: { sourceInstanceName: { eq: "media" } }) {.
When I try allImageSharp(filter: { id: { regex: "/media/" } }) { just display a blank window, but that's work fine like that allImageSharp {
javascript
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
const img_grid_style = {
display: "grid",
gridTemplateColumns: `repeat(auto-fill, 200px)`,
}
export default ({ data }) => (
<div>
<Layout title="IMAGE GRID"></Layout>
<div style={img_grid_style}>
{data.allImageSharp.edges.map(edge => (
<Img fluid={edge.node.fluid} />
))}
</div>
</div>
)
export const query = graphql`
query {
allImageSharp(filter: { sourceInstanceName: { eq: "media" } }) {
edges {
node {
id
fluid(maxWidth: 200, maxHeight: 200) {
...GatsbyImageSharpFluid
}
}
}
}
}
`
config
module.exports = {
plugins: [
`gatsby-transformer-sharp`,
{
resolve: `gatsby-plugin-sharp`,
options: {
// Available options and their defaults:
base64Width: 20,
// forceBase64Format: ``, // valid formats: png,jpg,webp // don't work on OSX
useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`,
stripMetadata: true,
defaultQuality: 50,
failOnError: true,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `media`,
path: `./media/`,
},
},
],
}
Change your path in your gatsby-source-filesystem to:
{
resolve: `gatsby-source-filesystem`,
options: {
name: `media`,
path: `${__dirname}/media/`,
},
},
The snippet above will match. rootOfYourProject/media, change it to your media path keeping the ${__dirname}.
Now, your filesystem can be filtered by media (without slashes).
export const query = graphql`
{
allFile(filter: {sourceInstanceName: {eq: "media"}}) {
nodes {
childImageSharp {
fluid {
base64
tracedSVG
srcWebp
srcSetWebp
originalImg
originalName
}
}
}
}
}
`
Since you can't use fragments in the GraphQL playground (localhost:8000/___graphql) I've used the extended version, however, you should use the ...GatsbyImageSharpFluid once applied to your code.
allFile or allImageSharp should do the trick.
I've fixed your project in this PR. The query was retrieving properly the results, however, you were missing some nested objects to get the final fluid image:
export default ({ data }) => {
return <div>
<Layout title="IMAGE GRID FROM SPECIFIC FOLDER"></Layout>
<div style={img_grid_style}>
{data.allFile.edges.map(({ node }) => (
<Img fluid={node.childImageSharp.fluid} />
))}
</div>
</div>
}