surveyjs / survey-creator

Scalable open-source survey software to generate dynamic JSON-driven forms within your JavaScript application. The form builder features a drag-and-drop UI, CSS Theme Editor, and GUI for conditional logic and form branching.
https://surveyjs.io/open-source
Other
898 stars 373 forks source link

Custom tab in survey-creator-js #5918

Open SamMousa opened 1 day ago

SamMousa commented 1 day ago

Are you requesting a feature, reporting a bug or ask a question?

Question

What is the current behavior?

I'm moving from survey-creator-knockout to survey-creator-js. I had a custom JSON editor tab (which uses Monaco editor) built in Svelte. I integrated this in knockout like this:

import * as ko from 'knockout';
import type { SvelteEditorTab } from './registerSvelteComponent';

const COMPONENT = 'svelte-component';

export default () => {
    // In dev mode re-register every time to catch changes
    if (ko.components.isRegistered(COMPONENT)) {
        ko.components.unregister(COMPONENT);
    }

    const element = document.createElement('div');
    element.style.width = '100%';
    element.style.height = '100%';
    ko.components.register(COMPONENT, {
        viewModel: {
            createViewModel(
                params: ko.components.ViewModelParams,
                componentInfo: ko.components.ComponentInfo
            ) {
                const tab: SvelteEditorTab = params.data;
                if (!(componentInfo.element.nextSibling instanceof HTMLDivElement)) {
                    throw new Error('Template must contain a single div element');
                }
                tab.setNode(componentInfo.element.nextSibling);

                return {} as ko.components.ViewModel;
            }
        } as ko.components.ViewModelFactory,
        template: [element]
    } as ko.components.Config);
};

The idea was that I register 1 component in knockout called svelte-component which then renders the correct component. The registration looks like this:

creator.addPluginTab('monaco', new SvelteEditorTab(creator, component), name, 'svelte-component');

How do I solve this in survey-creator-js? It seems I have to do it more in a react way, so I've done this:

ReactElementFactory.Instance.registerElement(
        'svelte-component',
        (props) => {
            console.warn('reactSvelteComponent', props);
            return createElement('div', props);
                 }
    );

The issue here is that in this callback props never contain a reference to the given plugin. As far as I can understand, this code: creator.addPluginTab('monaco', new SvelteEditorTab(creator, component), name, 'svelte-component'); basically says register the plugin SvelteEditorTab and render it using the view / component svelte-component, but I cannot reach one from the other.

Another issue is that since I'm not in the React eco system I want to be able to manipulate "my part" of the DOM directly. But nowhere do I get a reference to the DOM node for my tab.

How would I do this in Vanilla JS?

andrewtelnov commented 1 day ago

@SamMousa Please review our example.

Thank you, Andrew

SamMousa commented 1 day ago

I did, but it uses JSX which I don't use (and reasonably most non-react users won't be using.

And the example doesn't actually get references to the DOM nodes, it just creates react components recursively.

andrewtelnov commented 1 day ago

Yes, right. You can use the preact createElement function in this case.

Thank you, Andrew