# How to integrate TinyMCE with the all New Blazor Static Server render mode

**Blazor** static server-side rendering (**static SSR**), not to be confused with **interactive SSR**, has finally landed in .NET 8.

This mode does not require a websocket connection, but keep in mind pages are fully rendered on the server and delivered to the client as HTML. This means you can lose some of the exciting interactivity introduced by interactive **SSR** and **CSR** via **WebAssembly**. The upside is that without that constant websocket connection your application is now more scalable. Of course you can introduce interactivity back into the parts of your application that actually need it.

Now unto the main task at hand.

What we will try to achieve is integrating TinyMCE into your **Static SSR** Application without enabling any interactivity. We will accomplish this by configuring Javascript code to execute when a statically rendered page, possibly with enhanced navigation, is loaded or updated.

**Step 1.**  
Register with tinyMCE and get your free API Key

**Step 2.**  
Generate your Blazor Application. In this case I will just use the template that utilizes Interactive Auto, but per component/page. Not globally. With this mode you must enable interactivity where you need it, so by default everything is rendered in **Static SSR** Mode.

```plaintext
dotnet new blazor -int Auto -o MyTinyMceProject
```

**Step 3.**  
Enter the project directory and create a Razor Class Library (**RCL**)

```plaintext
dotnet new razorclasslib -o MyTinyMceScriptInitilizer
```

**Step 4.**  
Configure these projects such that the **RCL** is referenced by the main **Blazor** project

```plaintext
dotnet sln add MyTinyMceProject/MyTinyMceProject.csproj
dotnet sln add MyTinyMceScriptInitilizer/MyTinyMceScriptInitilizer.csproj
dotnet add MyTinyMceProject/MyTinyMceProject.csproj reference MyTinyMceScriptInitilizer/MyTinyMceScriptInitilizer.csproj
```

**Step 5.**  
In the **RCL** we need to create two files. In the root of the project create a razor component `MyPageScript.razor` with the following code.

```csharp
<page-script src="@Src"></page-script>

@code {
    [Parameter]
    [EditorRequired]
    public string Src { get; set; } = default!;
}
```

In the `wwwroot` folder of the **RCL** create a file `MyTinyMceScriptInitilizer.lib.module.js` with the following code.

```javascript
const pageScriptInfoBySrc = new Map();

function registerPageScriptElement(src) {
    if (!src) {
        throw new Error(
            'Must provide a non-empty value for the "src" attribute.'
        );
    }

    let pageScriptInfo = pageScriptInfoBySrc.get(src);

    if (pageScriptInfo) {
        pageScriptInfo.referenceCount++;
    } else {
        pageScriptInfo = { referenceCount: 1, module: null };
        pageScriptInfoBySrc.set(src, pageScriptInfo);
        initializePageScriptModule(src, pageScriptInfo);
    }
}

function unregisterPageScriptElement(src) {
    if (!src) {
        return;
    }

    const pageScriptInfo = pageScriptInfoBySrc.get(src);
    if (!pageScriptInfo) {
        return;
    }

    pageScriptInfo.referenceCount--;
}

async function initializePageScriptModule(src, pageScriptInfo) {
    if (src.startsWith('./')) {
        src = new URL(src.substr(2), document.baseURI).toString();
    }

    const module = await import(src);

    if (pageScriptInfo.referenceCount <= 0) {
        return;
    }

    pageScriptInfo.module = module;
    module.onLoad?.();
    module.onUpdate?.();
}

function onEnhancedLoad() {
    for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
        if (referenceCount <= 0) {
            module?.onDispose?.();
            pageScriptInfoBySrc.delete(src);
        }
    }

    for (const { module } of pageScriptInfoBySrc.values()) {
        module?.onUpdate?.();
    }
}

export function afterWebStarted(blazor) {
    customElements.define(
        'page-script',
        class extends HTMLElement {
            static observedAttributes = ['src'];

            attributeChangedCallback(name, oldValue, newValue) {
                if (name !== 'src') {
                    return;
                }

                this.src = newValue;
                unregisterPageScriptElement(oldValue);
                registerPageScriptElement(newValue);
            }

            disconnectedCallback() {
                unregisterPageScriptElement(this.src);
            }
        }
    );

    blazor.addEventListener('enhancedload', onEnhancedLoad);
}
```

**Step 6.**  
In the main `/Components/Pages` folder of the main project create two files.

The first file will be your **Blazor** component in which you want the TinyMCE Editor. We will call this page `MyTinyMcePage.razor` and in it place the following code.

```csharp
@page "/tinymce"

<MyTinyMceScriptInitilizer.MyPageScript Src="./Components/Pages/MyTinyMcePage.razor.js?tinymce" />

<EditForm Model="MyPageData" OnValidSubmit="HandleSubmit" FormName="tinymce-page" method="POST"/>
	<div>
		<label>Content:</label>
		<InputTextArea @bind-Value="MyPageData.Content" id="MyPageData_Content">
		</InputTextArea>
	</div>
</EditForm>

@code {

	[SupplyParameterFromForm(FormName = "tinyemce-page")]
	public MyPageModel MyPageData {get; set;} = new();

	private class MyPageModel
    	{
		   public string? Content { get; set; }
    	}
    	
    	public void HandleSubmit() {
    		Console.Writeline(MyPageData?.Content)
    	}
}
```

The second file will sit right next to the **Blazor** component and will be called `MyTinyMcePage.razor.js` and will contain the following code.

```javascript
TinyMceInit = function (selector) {
    tinymce.remove(`textarea#${selector}`);
    tinymce.init({
        selector: `textarea#${selector}`,
    });
};

export function onLoad() {
    TinyMceInit('MyPageData_Content');
}

export function onUpdate() {
    TinyMceInit('MyPageData_Content');

}

export function onDispose() {}
```

**Step 7.**  
Finally, update your `App.razor` component in the root of your main project to have the link to the tinyMCE CDN. place this

```xml
    <script src="https://cdn.tiny.cloud/1/<[YOUR_TINYMCE_API_CODE]>/tinymce/6/tinymce.min.js"
        referrerpolicy="origin"></script>
```

below

```xml
    <script src="_framework/blazor.web.js"></script>
```

That's it! Launch your project, `dotnet watch --project MyTinyMceProject --launch-profile https` , and enjoy your freshly minted TinyMCE editor.
