Blazor -  Criando um Editor RichText (Quill API)


Neste tutorial veremos como criar um editor RichText com base na API do Quill usando uma aplicação Blazor Server.

Hoje veremos um tutorial mostrando como criar um editor RichText em uma aplicação Blazor Server usando o componente open-source Quill.

Todas as funcionalidades implementadas no projeto Blazor serão feitas via JS interop usando a API do Quill que você pode consultar para detalhes neste link : https://quilljs.com/docs/quickstart/

Recursos usados:

Criando o projeto Blazor Server no VS Community 2019

bra o VS 2019 Community (versão mínima 16.4) e selecione a opção Create a New Project;

A seguir selecione a opção Blazor app e clique em next;

Informe o nome do projeto :  Blazor_EditorRichText, a localização e clique em Create;

A seguir teremos uma janela com duas opções :

  1. Blazor Server App
  2. Blazor WebAssembly App

Selecione a primeira opção - Blazor Server App. Não vamos usar autenticação e vamos habilitar o https.

Clique no botão Create para criar o projeto.

Antes de prosseguir vamos limpar o projeto excluindo os arquivos abaixo e suas referências:

Vamos também ajustar o arquivo NavMenu.razor deixando apenas a opção Home no menu.

Agora com o projeto criado e os ajustes feitos, a primeira coisa a fazer e criar um arquivo JavaScript chamdo BlazorQuill.js para acessar a API do Quill e definir as referências à API no arquivo _Host.cshtml.

Criando o arquivo javascript BlazorQuill

Crie uma pasta js dentro da pasta wwwroot do projeto e nesta pasta crie o arquivo BlazorQuill.js com o seguinte conteúdo:

(function () {
    window.QuillFunctions = {
        createQuill: function (quillElement) {
            var options = {
                debug: 'info',
                modules: {
                    toolbar: '#toolbar'
                },
                placeholder: 'Digite aqui',
                readOnly: false,
                theme: 'snow'
            };
            new Quill(quillElement, options);
        },
        getQuillContent: function (quillControl) {
            return JSON.stringify(quillControl.__quill.getContents());
        },
        getQuillText: function (quillControl) {
            return quillControl.__quill.getText();
        },
        getQuillHTML: function (quillControl) {
            return quillControl.__quill.root.innerHTML;
        },
        loadQuillContent: function (quillControl, quillContent) {
            content = JSON.parse(quillContent);
            return quillControl.__quill.setContents(content, 'api');
        },
        disableQuillEditor: function (quillControl) {
            quillControl.__quill.enable(false);
        }
    };
})();

Referenciando a API do Quill

Abra o arquivo _Hosts.chtml na pasta Pages e inclua as linhas em azul que referenciam a API do Quill conforme mostrado abaixo :

@page "/"
@namespace Blazor_EditorRichText.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor_EditorRichText</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet" />
    <link href="https://cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet" />

</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.server.js"></script>

    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
    <script src="js/BlazorQuill.js"></script>

</body>
</html>

Aqui estamos usando a distribuição CDN da API do Quill e incluindo referência aos arquivos de estilo e ao arquivo da API quill.js.

Definindo o código Blazor no componente Index

Abra o arquivo Index.razor na pasta Pages e inclua o código abaixo:

@page "/"
@inject IJSRuntime JSRuntime
@if (EditorEnabled)
{
    <br />
    <button class="btn btn-primary" @onclick="GetText">Texto</button>
    <button class="btn btn-primary" @onclick="GetHTML">HTML</button>
    <button class="btn btn-primary" @onclick="GetEditorContent">Conteúdo</button>
    <button class="btn btn-danger" @onclick="SaveContent">Salvar</button>
    <button class="btn btn-success" @onclick="LoadContent">Carregar</button>
    <button class="btn btn-info" @onclick="DisableQuillEditor">Desabilitar</button>
    <br />
    <div id="toolbar">
        <span class="ql-formats">
            <select class="ql-font">
                <option selected=""></option>
                <option value="serif"></option>
                <option value="monospace"></option>
            </select>
            <select class="ql-size">
                <option value="small"></option>
                <option selected=""></option>
                <option value="large"></option>
                <option value="huge"></option>
            </select>
        </span>
        <span class="ql-formats">
            <button class="ql-bold"></button>
            <button class="ql-italic"></button>
            <button class="ql-underline"></button>
            <button class="ql-strike"></button>
        </span>
        <span class="ql-formats">
            <select class="ql-color"></select>
            <select class="ql-background"></select>
        </span>
        <span class="ql-formats">
            <button class="ql-list" value="ordered"></button>
            <button class="ql-list" value="bullet"></button>
            <button class="ql-indent" value="-1"></button>
            <button class="ql-indent" value="+1"></button>
            <select class="ql-align">
                <option selected=""></option>
                <option value="center"></option>
                <option value="right"></option>
                <option value="justify"></option>
            </select>
        </span>
        <span class="ql-formats">
            <button class="ql-link"></button>
        </span>
    </div>
}
<div @ref="@divEditorElement" />
<div>
    @EditorContent
</div>
<div>
    @((MarkupString)@EditorHTMLContent)
</div>
@code {
    private string strSavedContent = "";
    private ElementReference divEditorElement;
    private string EditorContent;
    private string EditorHTMLContent;
    private bool EditorEnabled = true;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeAsync<string>(
                "QuillFunctions.createQuill", divEditorElement);
        }
    }
    async Task GetText()
    {
        EditorHTMLContent = "";
        EditorContent = await JSRuntime.InvokeAsync<string>(
            "QuillFunctions.getQuillText", divEditorElement);
    }
    async Task GetHTML()
    {
        EditorContent = "";
        EditorHTMLContent = await JSRuntime.InvokeAsync<string>(
            "QuillFunctions.getQuillHTML", divEditorElement);
    }
    async Task GetEditorContent()
    {
        EditorHTMLContent = "";
        EditorContent = await JSRuntime.InvokeAsync<string>(
            "QuillFunctions.getQuillContent", divEditorElement);
    }
    async Task SaveContent()
    {
        strSavedContent = await JSRuntime.InvokeAsync<string>(
            "QuillFunctions.getQuillContent", divEditorElement);
    }
    async Task LoadContent()
    {
        var QuillDelta = await JSRuntime.InvokeAsync<object>(
            "QuillFunctions.loadQuillContent", divEditorElement, strSavedContent);
    }
    async Task DisableQuillEditor()
    {
        EditorEnabled = false;
        await JSRuntime.InvokeAsync<object>(
            "QuillFunctions.disableQuillEditor", divEditorElement);
    }
}

Agora é só alegria...

Executando o projeto teremos o resultado abaixo:

Pegue o projeto aqui:  Blazor_EditorRichText.zip (sem as referências)

"Porque todos (os cristãos) devemos comparecer ante o tribunal de Cristo, para que cada um receba segundo o que tiver feito por meio do corpo, ou bem, ou mal."
2 Coríntios 5:10

Referências:


José Carlos Macoratti