josdejong / svelte-jsoneditor

A web-based tool to view, edit, format, repair, query, transform, and validate JSON
https://jsoneditoronline.org
Other
818 stars 108 forks source link

The cursor is going to the first line after each edit. #302

Closed aitiqad closed 6 months ago

aitiqad commented 10 months ago

URGENT HELP REQUIRED

I don't know why but, whenever I am in the text mode and try to edit my JSON the text cursor ( | ) is automatically going to the first line, after a single edit.

this is how my component looks like

import { useEffect, useRef } from 'react'
import { JSONEditor } from 'vanilla-jsoneditor' 
import "./SKREditor.css";

const SKREditor = (props) => {
  const refContainer = useRef(null)
  const refEditor = useRef(null)

  useEffect(() => {

    // create editor
    refEditor.current = new JSONEditor({
      target: refContainer.current,
      props: {}
    })

    return () => {
      // destroy editor
      if (refEditor.current) {
        refEditor.current.destroy()
        refEditor.current = null
      }
    }
  }, [])

  // update editor
  useEffect(() => {
    if (refEditor.current) {
      refEditor.current.updateProps(props)
      console.log('update',props)
    }
  }, [props])

  return <div className="skr-jsoneditor-react" ref={refContainer}  />
}

export default SKREditor

and this is how im using it in my parent component code

 <SKREditor
     content={{ json: jsonDesiredPropertiesValue }}
     onChange={(updatedContent) => { onChangeMethodCalled(updatedContent, 'jsonDesiredPropertiesValue') }}
 />

I've used this component thrice for three events (jsonInputValue, jsonPropertiesValue, jsonDesiredPropertiesValue)

  const onChangeMethodCalled = (updatedContent, eventVal) => {

        if (typeof updatedContent === 'object') {
            try {
                let parsedContent = {}
                if (updatedContent.json) {
                    parsedContent = updatedContent.json;
                }
                else if (updatedContent.text) {
                    parsedContent = JSON.parse(updatedContent.text);
                    // parsedContent = updatedContent.text;
                }
                // const parsedContent = JSON.parse(updatedContent.text);
                if (eventVal === 'jsonInputValue') {
                    setJsonInputValue(parsedContent);
                } else if (eventVal === 'jsonPropertiesValue') {
                    setJsonPropertiesValue(parsedContent);
                } else if (eventVal === 'jsonDesiredPropertiesValue') {
                    setJsonDesiredPropertiesValue(parsedContent);
                }
            } catch (error) {
                console.error('Parsing error:', error);
            }
        } else {
            console.warn('Unexpected content format:', updatedContent);
        }
    };
josdejong commented 10 months ago

The text mode loses focus when the text contents change. Looking at your code I see you store the state as json. That will give issues since the contents of the text mode cannot always be represented as JSON. For example: [1,2,3. Also, JSON loses any whitespacing like spaces or newlines, so if I change [1,2,3] to [1, 2, 3] in the editor and you parse it to JSON and then stringify it, the whitespacing is changed, which causes the editor to reset the cursor.

To solve this issue you will have to keep the original updatedContent (which can hold either { json } or { text }) in your state.

josdejong commented 10 months ago

Here is a React example: https://codesandbox.io/s/svelte-jsoneditor-react-59wxz

aitiqad commented 10 months ago

So how shall i keep the Updated content to {json} only? As per my requirement i need JSON only.

josdejong commented 10 months ago

As per my requirement i need JSON only.

If the user types the following in the editor, what do you want to do?

[
  1,
  2,
  3
aitiqad commented 10 months ago

If the user types these things, I want the Json Validation to work on and return an error.

josdejong commented 10 months ago

Indeed, so your application should hold the following state: either valid json, or invalid json as text plus a parse error. In your code example, the state only holds json in a variable parsedContent, but that is not enough.

aitiqad commented 10 months ago

Oh, I'm getting your point now. So if I pass content={{json:example, text:undefined}} It should work right? Or shall I separately declare it?

josdejong commented 10 months ago

You can just let the editor do it's thing and utilize it's Content type, that can hold both parsed JSON and an unparsed text string (read the docs and examples about that).

Only when you want to save the document, you can check whether the content is valid JSON, and if not show the user an error. At that point you can read out either updatedContent.json or JSON.parse(updatedContent.text) and store that in your database.

aitiqad commented 10 months ago

brother, I'm very new to react, so it would be really helpful if you tell me exactly where shall i make changes on my code. Please

josdejong commented 10 months ago

Sure, you can check out the following React example: https://codesandbox.io/s/svelte-jsoneditor-react-59wxz

aitiqad commented 10 months ago

I took reference from here only. My jsonInputValue, jsonPropertiesValue and jsonDesiredPropertiesValue are already declared useStates. whose data (JSON) are being fetched from an API. while in the React Example I found that the data has to be in a certain format that,

{
json: {
      example data
      example data
      ..
      ..
      ..
      example data
    },
    text: undefined
}
josdejong commented 10 months ago

I'm not sure what you mean, can you explain?

josdejong commented 6 months ago

Closing due to inactivity, please reopen if needed.