Coder Social home page Coder Social logo

onError do nothing about jsoneditor-react HOT 13 CLOSED

vankop avatar vankop commented on May 17, 2024
onError do nothing

from jsoneditor-react.

Comments (13)

ngmgit avatar ngmgit commented on May 17, 2024 3

If you are using ace mode then for now you can have onChangeText callback and have a debounced function, if needed, to get the errors from ace session.

<jsonEditorRef>.current.jsonEditor.aceEditor.getSession().getAnnotations();

And a better way is to subscribe to 'changeAnnotation' event for ace.

from jsoneditor-react.

AnnaRainier avatar AnnaRainier commented on May 17, 2024 3

this onError method fires on my component only if I trigger "filter, sort or transform contents" manually, I expected it to fire once an error occurs in JSON file. If I need to rely on JSON validity state, for, let's say, some button disabled state, how do I do that?

from jsoneditor-react.

Isaacgl68 avatar Isaacgl68 commented on May 17, 2024 2

you can use the onValidationError of the json editor
You just need to add it in the editor props (it will pass to the jeson editor as the editor is passing the ...rest props)

const onValidationError = (value)=>{
if (value && value.length > 0) {
//do
}
}
<Editor
...
onValidationError={onValidationError} />

from jsoneditor-react.

vankop avatar vankop commented on May 17, 2024

@zbyso23 PR wellcome.

from jsoneditor-react.

zbyso23 avatar zbyso23 commented on May 17, 2024

@zbyso23 PR wellcome.

okay, how to? I don't have experience with collaboration on GitHub project, trying create new branch - handle-errors but commit is impossible - don't have correct access rights

from jsoneditor-react.

emmanuelgautier avatar emmanuelgautier commented on May 17, 2024

You have to fork this project, then push the new branch you created into your newly created repo. After that, you should be able to create a new PR from the Github interface.

from jsoneditor-react.

zbyso23 avatar zbyso23 commented on May 17, 2024

thanks - I try to implement subscribe changeAnnotation, but I noticed strange behaviour of Ace editor - when is fired in callback, return empty object - but, I say "okay, I get manually", but when i call directly code like this:

const annotations = this.jsonEditor.aceEditor.getSession().getAnnotations();

in annotations return OLD error! then I fix for now by code like this:

setTimeout(() => {
   const annotations = this.jsonEditor.aceEditor.getSession().getAnnotations();
}, 150);

but is very dirty - time can be not enough on old computers :/
thrid issue what i registrer, even i call this code only once:

this.jsonEditor.aceEditor.getSession().on('changeAnnotation', this.handleError);

is every time called twice...
if anybody notice similar behaviour i very thanks for any help :)

from jsoneditor-react.

vankop avatar vankop commented on May 17, 2024

@zbyso23 You need to create issue in upstream dependency

from jsoneditor-react.

zbyso23 avatar zbyso23 commented on May 17, 2024

I use now this hack

    handleChange() {
        if (this.props.onChange) {
            try {
                const text = this.jsonEditor.getText();
                if (text === '') {
                    this.props.onChange(null);
                }

                const currentJson = this.jsonEditor.get();
                if (this.props.value !== currentJson) {
                    this.props.onChange(currentJson);
                }
            } catch (err) {
                this.err = err;
                if(this.props.onError) {
                  const error = typeof err === 'object' ? err.message : err;
                  this.props.onError(error);
                }
            }
        }
    }

works good

from jsoneditor-react.

zbyso23 avatar zbyso23 commented on May 17, 2024

for even handling ACE Editor errors prepared this ugly version, please don't beat me 😄

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import JSONEditor from 'jsoneditor/dist/jsoneditor';
import 'jsoneditor/dist/jsoneditor.css';
// import './fixAce.css';

/**
 * @typedef {{
 * tree: string,
 * view: string,
 * form: string,
 * code: string,
 * text: string,
 * allValues: Array<string>
 * }} TJsonEditorModes
 */
const modes = {
    tree: 'tree',
    view: 'view',
    form: 'form',
    code: 'code',
    text: 'text'
};

const values = Object.values(modes);

const hashCodeACE = s => s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              

modes.allValues = values;

/**
 * @type {object}
 * @property {object} [value]
 * @property {string} [mode='tree'] - Set the editor mode.
 * @property {string} [name=undefined] - Initial field name for the root node
 * @property {object} [schema] - Validate the JSON object against a JSON schema.
 * @property {object} [schemaRefs] - Schemas that are referenced using
 * the $ref property
 * @property {Function} [onChange] - Set a callback function
 * triggered when the contents of the JSONEditor change.
 * Called without parameters. Will only be triggered on changes made by the user.
 * Return new json.
 * @property {Function} [onError] - Set a callback function triggered when an error occurs.
 * Invoked with the error as first argument.
 * The callback is only invoked for errors triggered by a users action,
 * like switching from code mode to tree mode or clicking
 * the Format button whilst the editor doesn't contain valid JSON.
 * @property {Function} [onErrorAce] - Set a callback function triggered when an error of ACEditor occurs.
 * @property {Function} [onModeChange] - Set a callback function
 * triggered right after the mode is changed by the user.
 * @property {object} [ace] - Provide a version of the Ace editor.
 * Only applicable when mode is code
 * @property {object} [ajv] - Provide a instance of ajv,
 * the library used for JSON schema validation.
 * @property {string} [theme] - Set the Ace editor theme,
 * uses included 'ace/theme/jsoneditor' by default.
 * @property {boolean} [history=false] - Enables history,
 * adds a button Undo and Redo to the menu of the JSONEditor. Only applicable when
 * mode is 'tree' or 'form'
 * @property {boolean} [navigationBar=true] - Adds navigation bar to the menu
 * the navigation bar visualize the current position on the
 * tree structure as well as allows breadcrumbs navigation.
 * @property {boolean} [statusBar=true] - Adds status bar to the buttom of the editor
 * the status bar shows the cursor position and a count of the selected characters.
 * Only applicable when mode is 'code' or 'text'.
 * @property {boolean} [search=true] - Enables a search box in
 * the upper right corner of the JSONEditor.
 * @property {Array<string>} [allowedModes] - Create a box in the editor menu where
 * the user can switch between the specified modes.
 * @property {(string|PropTypes.elementType)} [tag='div'] - Html element, or react element to render
 * @property {object} [htmlElementProps] - html element custom props
 * @property {Function} [innerRef] - callback to get html element reference
 */
export default class JsonEditorACE extends Component {
    constructor(props) {
        super(props);

        this.htmlElementRef = null;
        this.jsonEditor = null;

        this.handleChange = this.handleChange.bind(this);
        this.handleErrorACE = this.handleErrorACE.bind(this);
        this.setRef = this.setRef.bind(this);
        this.collapseAll = this.collapseAll.bind(this);
        this.expandAll = this.expandAll.bind(this);
        this.focus = this.focus.bind(this);

        this.lastErrorACE = null;
        this.lastErrorACEHash = '';
    }

    componentDidMount() {
        const {
            allowedModes,
            innerRef,
            htmlElementProps,
            tag,
            onChange,
            onErrorAce,
            ...rest
        } = this.props;

        this.createEditor({
            ...rest,
            modes: allowedModes
        });
    }

    // eslint-disable-next-line react/sort-comp
    componentDidUpdate({
        allowedModes,
        schema,
        name,
        theme,
        schemaRefs,
        innerRef,
        htmlElementProps,
        tag,
        onChange,
        ...rest
    }) {
        if (this.jsonEditor) {
            if (theme !== this.props.theme) {
                this.createEditor({
                    ...rest,
                    theme,
                    modes: allowedModes
                });
            } else {
                if (schema !== this.props.schema
                    || schemaRefs !== this.props.schemaRefs
                ) {
                    this.jsonEditor.setSchema(schema, schemaRefs);
                }

                if (name !== this.jsonEditor.getName()) {
                    this.jsonEditor.setName(name);
                }
            }
        }
    }

    shouldComponentUpdate({ htmlElementProps }) {
        return htmlElementProps !== this.props.htmlElementProps;
    }

    componentWillUnmount() {
        if (this.jsonEditor) {
            this.jsonEditor.destroy();
            this.jsonEditor = null;
        }
    }

    setRef(element) {
        this.htmlElementRef = element;
        if (this.props.innerRef) {
            this.props.innerRef(element);
        }
    }

    createEditor({ value, ...rest }) {
        if (this.jsonEditor) {
            this.jsonEditor.destroy();
        }
        this.jsonEditor = new JSONEditor(this.htmlElementRef, {
            onChange: this.handleChange,
            onError: this.handleErrorACE,
            ...rest
        });
        this.jsonEditor.set(value);
        if(this.jsonEditor && this.jsonEditor.aceEditor)
        {
          this.jsonEditor.aceEditor.getSession().on('changeAnnotation', this.handleErrorACE);
        }
        window['jsoneditor'] = this.jsonEditor;
    }

    handleChange() {
        if (this.props.onChange) {
            try {
                const text = this.jsonEditor.getText();
                if (text === '') {
                    this.props.onChange(null);
                }

                const currentJson = this.jsonEditor.get();
                if (this.props.value !== currentJson) {
                    this.props.onChange(currentJson);
                }
            } catch (err) {
                this.err = err;
                if(this.props.onError) {
                  const error = typeof err === 'object' ? err.message : err;
                  this.props.onError(error);
                }
            }
        }
    }

    handleErrorACE() {
        if(!this.jsonEditor || !this.props.onErrorAce) return;
        const deltaTreshold = 200;
        const handleErrorDelta = (this.lastErrorACE) ? (new Date().getTime()) - this.lastErrorACE : 0;
        try {
            if(this.jsonEditor.aceEditor)
            {
              setTimeout(() => {
                if(!this.jsonEditor || !this.jsonEditor.aceEditor) return;
                const annotations = this.jsonEditor.aceEditor.getSession().getAnnotations();
                const errors = annotations.filter(annot => annot.type === 'error').map(annot => {
                  return { ...annot, message: `${annot.text} on line ${annot.row} and column ${annot.column}` }
                });
                if (errors.length > 0) {
                  const errorHash = hashCodeACE(JSON.stringify(errors));
                  if(handleErrorDelta < deltaTreshold && errorHash === this.lastErrorACEHash) return;
                  this.lastErrorACEHash = errorHash;
                  this.props.onErrorAce(errors);
                }
              }, deltaTreshold);
            }
        } catch (err) {
            this.err = err;
        }
        this.lastErrorACE = new Date().getTime();
    }

    collapseAll() {
        if (this.jsonEditor) {
            this.jsonEditor.collapseAll();
        }
    }

    expandAll() {
        if (this.jsonEditor) {
            this.jsonEditor.expandAll();
        }
    }

    focus() {
        if (this.jsonEditor) {
            this.jsonEditor.focus();
        }
    }

    render() {
        const {
            htmlElementProps,
            tag
        } = this.props;

        return React.createElement(
            tag,
            {
                ...htmlElementProps,
                ref: this.setRef
            }
        );
    }
}

JsonEditorACE.propTypes = {
    //  jsoneditor props
    value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
    mode: PropTypes.oneOf(values),
    name: PropTypes.string,
    schema: PropTypes.object,
    schemaRefs: PropTypes.object,

    onChange: PropTypes.func,
    onError: PropTypes.func,
    onErrorAce: PropTypes.func,
    onModeChange: PropTypes.func,

    ace: PropTypes.object,
    ajv: PropTypes.object,
    theme: PropTypes.string,
    history: PropTypes.bool,
    navigationBar: PropTypes.bool,
    statusBar: PropTypes.bool,
    search: PropTypes.bool,
    allowedModes: PropTypes.arrayOf(PropTypes.oneOf(values)),

    //  custom props
    tag: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
    htmlElementProps: PropTypes.object,
    innerRef: PropTypes.func,
};

JsonEditorACE.defaultProps = {
    tag: 'div',
    mode: modes.tree,
    history: false,
    search: true,
    navigationBar: true,
    statusBar: true,
};

/**
 * @type TJsonEditorModes
 */
JsonEditorACE.modes = modes;

from jsoneditor-react.

vankop avatar vankop commented on May 17, 2024

PR welcome

from jsoneditor-react.

vankop avatar vankop commented on May 17, 2024

in jsoneditor@9 there is an option onError, so current prop onError will be passed in editor options

from jsoneditor-react.

zbyso23 avatar zbyso23 commented on May 17, 2024

I solve this problem by code above (10 Jun 2020), but it's not part of current code - i use standalone file Editor.tsx in my project

from jsoneditor-react.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.