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

Custom menu item does not redraw when disabled state changes #298

Closed semicolin closed 10 months ago

semicolin commented 11 months ago

I'm using vanilla-jsoneditor in an Angular application. I added a custom "save" button on the menu. The menu does not redraw when disabled state changes (unless the state of built-in buttons also changes coincidentally). I need a way to trigger refresh of the menu from onChange function.

    this.editor = new JSONEditor({
      target,
      props: {
        content: { json: this.json },
        mode: Mode.text,
        onChange: (content: Content, previousContent: Content, changeStatus: OnChangeStatus) => {
          this.canSave = !changeStatus.contentErrors;
        },
        onRenderMenu: (items: MenuItem[]) => {
          return [
            ...items,
            {
              type: 'button',
              icon: faSave as any,
              title: 'Save Changes',
              disabled: !this.canSave,
              onClick: () => console.log('click'),
            },
          ];
        },
      },
    });
josdejong commented 10 months ago

That is indeed a good question, outside of the Svelte lifecycle this doesn't happen magically.

What you can do is create a createOnRenderMenu function which creates the onRenderMenu based on the canSave state:

function createOnRenderMenu(canSave) {
  return function onRenderMenu (items: MenuItem[]) {
    return [
      ...items,
      {
        type: 'button',
        icon: faSave as any,
        title: 'Save Changes',
        disabled: !canSave,
        onClick: () => console.log('click'),
      },
    ];
  }
}

Then, create the menu on creation of the editor, and re-create it whenever the state of the menu (canSave) changes:

this.editor = new JSONEditor({
  target,
  props: {
    content: { json: this.json },
    mode: Mode.text,
    onChange: (content: Content, previousContent: Content, changeStatus: OnChangeStatus) => {
      this.canSave = !changeStatus.contentErrors;
      this.editor.updateProps({
        onRenderMenu: createOnRenderMenu(this.canSave)
      })
    },
    onRenderMenu: createOnRenderMenu(this.canSave),
  },
});
semicolin commented 10 months ago

Good solution. Thank you!

josdejong commented 10 months ago

👍