Search code examples
sveltereact-propsmonaco-editorsubscribe

How does this props passing method which includes a subscriber in the onMount directive work?


I'm trying to use Monaco Editor in Svelte. I found this snippet online and it has an interesting way of defining the component. It looks like it declares this content object in the onMount phase which should allow a parent component to subscribe to the editor.onDidChangeModelContent event. However, I can't tell how could a parent component use the content as a prop. Maybe I could get some help?

// MonacoEditor.svelte
let subscriptions = [];
export let content;
onMount(async () => {
   editor.onDidChangeModelContent(() => {
       const text = editor.getValue();
       subscriptions.forEach((sub) => sub(text));
   });
   content = {
       subscribe(func) {
           subscriptions.push(func);
           return () => {
               subscriptions = subscriptions.filter((sub) => sub != func);
           };
       },
       set(val) {
           editor.setValue(val);
       },
   };
   return () => {
       editor.dispose();
   };
});

I tried to use binding in the parent component and declaring the content in an onMount directive inside the parent component, none of it makes total sense and none of it worked...


Solution

  • I used the Monaco Editor in one of my SvelteKit projects. I used it through the npm package @monaco-editor/loader, which makes it a bit easier to use it than using their "ordinary" npm package (at least it was like this a year ago). Here is the code I have in SvelteKit to use it:

    src/lib/CodeEditor.svelte

    <script>
        
        export let code = ""
        
        import monacoLoader from '@monaco-editor/loader'
        
        let monacoEditor
        
        async function showEditor(editorContainer){
            
            const monaco = await monacoLoader.init()
            
            monacoEditor = monaco.editor.create(editorContainer, {
                value: code,
                automaticLayout: true,
                language: 'javascript',
            })
            
        }
        
        export function getCode(){
            return monacoEditor.getValue()
        }
        
    </script>
    
    <div
        use:showEditor
    />
    

    And then use it in other Svelte components like this:

    <script>
        
        import CodeEditor from '$lib/CodeEditor.svelte'
        
        let codeEditor
        
        function alertCode(){
            
            const code = codeEditor.getCode()
            
            alert(code)
            
        }
        
    </script>
    
    <button on:click={alertCode}>
        Alert Code
    </button>
    
    <CodeEditor
        code="// The code"
        bind:this={codeEditor}
    />
    

    (the code in my project is much bigger than this, so I removed parts that I thought was irrelevant, I hope I didn't remove too much ^^')