Start monaco with required jsonschema fields as the default value

125 Views Asked by At

I'm using monaco-yaml with React and have a requirement where I need to show the editor with the required values from a jsonschema.

Here's a simplified snippet of my code:

export const Editor: FC = () => {
  const [editor, setEditor] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
  const monacoEl = useRef<HTMLElement>(null);

  useEffect(() => {
    if (monacoEl.current) {
      configureMonacoYaml(monaco, {
        validate: true,
        format: true,
        enableSchemaRequest: true,
        hover: true,
        completion: true,
        schemas: [
          {
            uri: "http://myserver/foo-schema.json",
            fileMatch: ["*"],
            schema: {
              type: "object",
              additionalProperties: false,
              required: ["obj"],
              properties: {
                obj: {
                  type: "object",
                  required: ["str1", "str2"],
                  properties: {
                    str1: {
                      default: "stringValue1",
                      type: "string",
                    },
                    str2: {
                      type: "string",
                    },
                    str3: {
                      type: "string",
                    }
                  },
                },
                num: {
                  type: "number"
                },
              },
            },
          }
        ],
      });

      setEditor((ed) => {
        if (ed) return ed;

        const monacoEditor = monaco.editor.create(monacoEl.current!, {
          language: "yaml",
          automaticLayout: true,
          value: "",
        });

        return monacoEditor;
      });
    }

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [editor]);

  return (
      <Box ref={monacoEl} className="react-monaco-editor-container" />
  );
};

I want the default value of the editor when it mounts to be the required values from the provided jsonschema which in this case should be

obj:
  str1: stringValue1
  str2: 

Currently, I trigger the suggestion popup and accept the first suggestion but it doesn't work as expected all the time probably because the suggestions haven't loaded yet when I trigger acceptSelectedSuggestion:

useEffect(() => {
    if (!editor || editor.getValue().trim().length) {
      return;
    }

    const triggerSuggestionAction = editor.getAction("editor.action.triggerSuggest");

    if (!triggerSuggestionAction) {
      return;
    }

    triggerSuggestionAction.run().then(() => {
      // This is flaky because of the 500ms hardcoded delay
      setTimeout(() => {
        editor.trigger("", "acceptSelectedSuggestion", "");
      }, 500);
    });
}, [editor]);

Is there a event which gets emitted when suggestions have loaded so that I can wait for it before calling acceptSelectedSuggestion? Or is there a better way of doing this?

0

There are 0 best solutions below