This post demonstrates how to switch out the Markdown editor of ABPs CMS Kit with GrapesJS - based on an issue we created here.
We are just showing a proof of concept here.
You can find the source code here: https://github.com/Chrobyte/abp-grapesjs
So, we need an ABP application with CMS Kit. Let's do that.
First we create a new app using abp new Cb.Abp.GrapesJs -t app -u blazor-server --theme leptonx-lite
.
After that, we install the cms kit.
Do not forget to run DbMigrator
We will make use of ABP's bundling system.
add these npm packages to your package.json?
.
...
"grapesjs": "0.21.13",
"grapesjs-blocks-basic": "1.0.2",
"grapesjs-component-countdown": "1.0.2",
"grapesjs-custom-code": "1.0.2",
"grapesjs-parser-postcss": "1.0.3",
"grapesjs-plugin-export": "1.0.12",
"grapesjs-plugin-forms": "2.0.6",
"grapesjs-preset-webpage": "1.0.3",
"grapesjs-style-bg": "2.0.2",
"grapesjs-tabs": "1.0.6",
"grapesjs-tooltip": "0.1.8",
"grapesjs-touch": "0.1.1",
"grapesjs-tui-image-editor": "1.0.2",
"grapesjs-typed": "2.0.1",
"grapick": "0.1.13"
...
change abp.resourcemapping.js
to this:
module.exports = {
aliases: {
"@node_modules": "./node_modules",
"@libs": "./wwwroot/libs"
},
clean: [
],
mappings: {
"@node_modules/grapesjs/dist/grapes.min.js": "@libs/grapesjs/js",
"@node_modules/grapesjs/dist/css/grapes.min.css": "@libs/grapesjs/css",
"@node_modules/grapesjs/locale": "@libs/grapesjs/locale",
"@node_modules/grapesjs-blocks-basic/dist": "@libs/grapesjs-blocks-basic",
"@node_modules/grapesjs-component-countdown/dist": "@libs/grapesjs-component-countdown",
"@node_modules/grapesjs-component-countdown/dist": "@libs/grapesjs-component-countdown",
"@node_modules/grapesjs-custom-code/dist": "@libs/grapesjs-custom-code",
"@node_modules/grapesjs-parser-postcss/dist": "@libs/grapesjs-parser-postcss",
"@node_modules/grapesjs-plugin-export/dist": "@libs/grapesjs-plugin-export",
"@node_modules/grapesjs-plugin-forms/dist": "@libs/grapesjs-plugin-forms",
"@node_modules/grapesjs-preset-webpage/dist": "@libs/grapesjs-preset-webpage",
"@node_modules/grapesjs-style-bg/dist": "@libs/grapesjs-style-bg",
"@node_modules/grapesjs-style-gradient/dist": "@libs/grapesjs-style-gradient",
"@node_modules/grapesjs-tabs/dist": "@libs/grapesjs-tabs",
"@node_modules/grapesjs-tooltip/dist": "@libs/grapesjs-tooltip",
"@node_modules/grapesjs-touch/dist": "@libs/grapesjs-touch",
"@node_modules/grapesjs-tui-image-editor/dist": "@libs/grapesjs-tui-image-editor",
"@node_modules/grapesjs-typed/dist": "@libs/grapesjs-typed",
"@node_modules/grapick/dist": "@libs/grapick"
}
};
now, under your wwwroot folder, add another folder called scripts
and create a file called grapes-script.js
with the following content:
// grapes.js
let editor = null;
window.initializeGrapes = function(elementId) {
editor = grapesjs.init({
container: '#' + elementId,
fromElement: true,
showOffsets: true,
assetManager: {
embedAsBase64: true,
},
selectorManager: { componentFirst: true },
styleManager: {
sectors: [{
name: 'General',
properties: [
{
extend: 'float',
type: 'radio',
default: 'none',
options: [
{ value: 'none', className: 'fa fa-times' },
{ value: 'left', className: 'fa fa-align-left' },
{ value: 'right', className: 'fa fa-align-right' }
],
},
'display',
{ extend: 'position', type: 'select' },
'top',
'right',
'left',
'bottom',
],
}, {
name: 'Dimension',
open: false,
properties: [
'width',
{
id: 'flex-width',
type: 'integer',
name: 'Width',
units: ['px', '%'],
property: 'flex-basis',
toRequire: 1,
},
'height',
'max-width',
'min-height',
'margin',
'padding'
],
}, {
name: 'Typography',
open: false,
properties: [
'font-family',
'font-size',
'font-weight',
'letter-spacing',
'color',
'line-height',
{
extend: 'text-align',
options: [
{ id: 'left', label: 'Left', className: 'fa fa-align-left' },
{ id: 'center', label: 'Center', className: 'fa fa-align-center' },
{ id: 'right', label: 'Right', className: 'fa fa-align-right' },
{ id: 'justify', label: 'Justify', className: 'fa fa-align-justify' }
],
},
{
property: 'text-decoration',
type: 'radio',
default: 'none',
options: [
{ id: 'none', label: 'None', className: 'fa fa-times' },
{ id: 'underline', label: 'underline', className: 'fa fa-underline' },
{ id: 'line-through', label: 'Line-through', className: 'fa fa-strikethrough' }
],
},
'text-shadow'
],
}, {
name: 'Decorations',
open: false,
properties: [
'opacity',
'border-radius',
'border',
'box-shadow',
'background', // { id: 'background-bg', property: 'background', type: 'bg' }
],
}, {
name: 'Extra',
open: false,
buildProps: [
'transition',
'perspective',
'transform'
],
}, {
name: 'Flex',
open: false,
properties: [{
name: 'Flex Container',
property: 'display',
type: 'select',
defaults: 'block',
list: [
{ value: 'block', name: 'Disable' },
{ value: 'flex', name: 'Enable' }
],
}, {
name: 'Flex Parent',
property: 'label-parent-flex',
type: 'integer',
}, {
name: 'Direction',
property: 'flex-direction',
type: 'radio',
defaults: 'row',
list: [{
value: 'row',
name: 'Row',
className: 'icons-flex icon-dir-row',
title: 'Row',
}, {
value: 'row-reverse',
name: 'Row reverse',
className: 'icons-flex icon-dir-row-rev',
title: 'Row reverse',
}, {
value: 'column',
name: 'Column',
title: 'Column',
className: 'icons-flex icon-dir-col',
}, {
value: 'column-reverse',
name: 'Column reverse',
title: 'Column reverse',
className: 'icons-flex icon-dir-col-rev',
}],
}, {
name: 'Justify',
property: 'justify-content',
type: 'radio',
defaults: 'flex-start',
list: [{
value: 'flex-start',
className: 'icons-flex icon-just-start',
title: 'Start',
}, {
value: 'flex-end',
title: 'End',
className: 'icons-flex icon-just-end',
}, {
value: 'space-between',
title: 'Space between',
className: 'icons-flex icon-just-sp-bet',
}, {
value: 'space-around',
title: 'Space around',
className: 'icons-flex icon-just-sp-ar',
}, {
value: 'center',
title: 'Center',
className: 'icons-flex icon-just-sp-cent',
}],
}, {
name: 'Align',
property: 'align-items',
type: 'radio',
defaults: 'center',
list: [{
value: 'flex-start',
title: 'Start',
className: 'icons-flex icon-al-start',
}, {
value: 'flex-end',
title: 'End',
className: 'icons-flex icon-al-end',
}, {
value: 'stretch',
title: 'Stretch',
className: 'icons-flex icon-al-str',
}, {
value: 'center',
title: 'Center',
className: 'icons-flex icon-al-center',
}],
}, {
name: 'Flex Children',
property: 'label-parent-flex',
type: 'integer',
}, {
name: 'Order',
property: 'order',
type: 'integer',
defaults: 0,
min: 0
}, {
name: 'Flex',
property: 'flex',
type: 'composite',
properties: [{
name: 'Grow',
property: 'flex-grow',
type: 'integer',
defaults: 0,
min: 0
}, {
name: 'Shrink',
property: 'flex-shrink',
type: 'integer',
defaults: 0,
min: 0
}, {
name: 'Basis',
property: 'flex-basis',
type: 'integer',
units: ['px', '%', ''],
unit: '',
defaults: 'auto',
}],
}, {
name: 'Align',
property: 'align-self',
type: 'radio',
defaults: 'auto',
list: [{
value: 'auto',
name: 'Auto',
}, {
value: 'flex-start',
title: 'Start',
className: 'icons-flex icon-al-start',
}, {
value: 'flex-end',
title: 'End',
className: 'icons-flex icon-al-end',
}, {
value: 'stretch',
title: 'Stretch',
className: 'icons-flex icon-al-str',
}, {
value: 'center',
title: 'Center',
className: 'icons-flex icon-al-center',
}],
}]
}
],
},
plugins: [
'gjs-blocks-basic',
'grapesjs-plugin-forms',
'grapesjs-component-countdown',
'grapesjs-plugin-export',
'grapesjs-tabs',
'grapesjs-custom-code',
'grapesjs-touch',
'grapesjs-parser-postcss',
'grapesjs-tooltip',
'grapesjs-tui-image-editor',
'grapesjs-typed',
'grapesjs-style-bg',
'grapesjs-preset-webpage',
],
});
};
window.getGrapesContent = function () {
var html = editor.getHtml();
var css = editor.getCss();
return { html: html, css: css };
};
window.setGrapesContent = function (html, css) {
editor.setComponents(html);
editor.setStyle(css);
};
Create a new folder called Bundling
on the root of your Blazor project to then add the two files below.
add GrapesJsScriptContributor.cs
:
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Cb.Abp.GrapesJs.Blazor.Bundling;
public class GrapesJsScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/scripts/grapes-script.js");
context.Files.AddIfNotContains("/libs/grapesjs/js/grapes.min.js");
// languages
context.Files.AddIfNotContains("/libs/grapes/locale/ar.js");
context.Files.AddIfNotContains("/libs/grapes/locale/bs.js");
context.Files.AddIfNotContains("/libs/grapes/locale/ca.js");
context.Files.AddIfNotContains("/libs/grapes/locale/de.js");
context.Files.AddIfNotContains("/libs/grapes/locale/el.js");
context.Files.AddIfNotContains("/libs/grapes/locale/en.js");
context.Files.AddIfNotContains("/libs/grapes/locale/fa.js");
context.Files.AddIfNotContains("/libs/grapes/locale/fr.js");
context.Files.AddIfNotContains("/libs/grapes/locale/he.js");
context.Files.AddIfNotContains("/libs/grapes/locale/index.js");
context.Files.AddIfNotContains("/libs/grapes/locale/it.js");
context.Files.AddIfNotContains("/libs/grapes/locale/ko.js");
context.Files.AddIfNotContains("/libs/grapes/locale/nb.js");
context.Files.AddIfNotContains("/libs/grapes/locale/nl.js");
context.Files.AddIfNotContains("/libs/grapes/locale/pl.js");
context.Files.AddIfNotContains("/libs/grapes/locale/pt.js");
context.Files.AddIfNotContains("/libs/grapes/locale/se.js");
context.Files.AddIfNotContains("/libs/grapes/locale/tr.js");
context.Files.AddIfNotContains("/libs/grapes/locale/vi.js");
context.Files.AddIfNotContains("/libs/grapes/locale/zh.js");
context.Files.AddIfNotContains("/libs/grapesjs-blocks-basic/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-blocks-basic/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-blocks-basic/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-component-countdown/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-component-countdown/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-component-countdown/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-custom-code/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-custom-code/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-custom-code/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-parser-postcss/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-parser-postcss/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-parser-postcss/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-export/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-export/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-export/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-forms/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-forms/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-plugin-forms/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-preset-webpage/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-preset-webpage/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-preset-webpage/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-style-bg/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-style-bg/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-style-bg/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-style-gradient/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-style-gradient/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-style-gradient/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-tabs/grapesjs-tabs.min.js");
context.Files.AddIfNotContains("/libs/grapesjs-tabs/grapesjs-tabs.min.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-tooltip/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-tooltip/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-tooltip/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-touch/grapesjs-touch.min.js");
context.Files.AddIfNotContains("/libs/grapesjs-touch/grapesjs-touch.min.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-tui-image-editor/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-tui-image-editor/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-tui-image-editor/index.js.map");
context.Files.AddIfNotContains("/libs/grapesjs-typed/index.js");
context.Files.AddIfNotContains("/libs/grapesjs-typed/index.d.js");
context.Files.AddIfNotContains("/libs/grapesjs-typed/index.js.map");
context.Files.AddIfNotContains("/libs/grapick/grapick.min.js");
}
}
add GrapesJsStyleContributor.cs
:
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Cb.Abp.GrapesJs.Blazor.Bundling;
public class GrapesJsStyleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/grapesjs/css/grapes.min.css");
context.Files.AddIfNotContains("/libs/grapick/grapick.min.css");
}
}
Now, we will use these two contributors by updating the content of our blazor module.
private void ConfigureBundles()
{
Configure<AbpBundlingOptions>(options =>
{
// MVC UI
options.StyleBundles.Configure(
LeptonXLiteThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
//BLAZOR UI
options.StyleBundles.Configure(
BlazorLeptonXLiteThemeBundles.Styles.Global,
bundle =>
{
bundle.AddContributors(typeof(GrapesJsStyleContributor)); // ADD THIS
bundle.AddFiles("/blazor-global-styles.css");
//You can remove the following line if you don't use Blazor CSS isolation for components
bundle.AddFiles(new BundleFile("/Cb.Abp.GrapesJs.Blazor.styles.css", true));
}
);
// ADD THIS
options.ScriptBundles.Configure(
BlazorLeptonXLiteThemeBundles.Scripts.Global,
bundle =>
{
bundle.AddContributors(typeof(GrapesJsScriptContributor));
});
});
}
Now we need to run abp-install-libs
so that we get our new npm packages.
Now comes the exiting part.
As a matter of fact, I just realized that the free CMS Kit only has ASP .NET MVC :-| But we are using Blazor. Therefore we will just punch together something new in Blazor. Shame on me >.< It will be ugly - but after all we are just doing a PoC here.
First, Add Blazorise.Markdown to your *.csproj.
<PackageReference Include="Blazorise.Markdown" Version="1.5.2" />
Now, we'll create a new Component for the GrapesJS Editor under Components/CmsKit.
MyCmsContentBuilderComponent.razor
@inherits GrapesJsComponentBase
<div id="gjs" style="height: 250px; overflow: hidden; width: 100%;" class="gjs-editor-cont"></div>
MyCmsContentBuilderComponent.razor.cs
using Blazorise.Markdown;
using Blazorise;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System;
using Volo.Abp.Content;
using Volo.Abp;
using Volo.CmsKit.Admin.MediaDescriptors;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Web.Contents;
using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents;
using System.Linq;
using Volo.CmsKit.Admin.Contents;
namespace Cb.Abp.GrapesJs.Blazor.Components.CmsKit;
public partial class MyCmsContentBuilderComponent
{
[Inject]
protected IJSRuntime JsRuntime { get; set; } = default!;
[Parameter]
public string Value { get; set; } = default!;
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string Css { get; set; } = default!;
[Parameter]
public EventCallback<string> CssChanged { get; set; }
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JsRuntime.InvokeVoidAsync("initializeGrapes", "gjs");
await JsRuntime.InvokeVoidAsync("setGrapesContent", Value ?? string.Empty, Css ?? string.Empty);
}
}
protected virtual Task OnValueChanged(string value)
{
Value = value;
ValueChanged.InvokeAsync(value);
return Task.CompletedTask;
}
public async Task<GrapesContent> GetGrapesContent()
{
var content = await JsRuntime.InvokeAsync<GrapesContent>("getGrapesContent");
return content;
}
public class GrapesContent
{
public string Html { get; set; } = default!;
public string Css { get; set; } = default!;
}
}
You know the deal.
GrapesJsMenus.cs
namespace Cb.Abp.GrapesJs.Blazor.Menus;
public class GrapesJsMenus
{
private const string Prefix = "GrapesJs";
public const string Home = Prefix + ".Home";
// ADD this
public class CmsTest
{
private const string _myPrefix = Prefix + ".CmsTest";
public const string Create = _myPrefix + ".Create";
public const string Update = _myPrefix + ".Update";
}
}
GrapesJsMenuContributor.cs
using System.Threading.Tasks;
using Cb.Abp.GrapesJs.Localization;
using Cb.Abp.GrapesJs.MultiTenancy;
using Volo.Abp.Identity.Blazor;
using Volo.Abp.SettingManagement.Blazor.Menus;
using Volo.Abp.TenantManagement.Blazor.Navigation;
using Volo.Abp.UI.Navigation;
namespace Cb.Abp.GrapesJs.Blazor.Menus;
public class GrapesJsMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.Main)
{
await ConfigureMainMenuAsync(context);
}
}
private Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
var administration = context.Menu.GetAdministration();
var l = context.GetLocalizer<GrapesJsResource>();
context.Menu.Items.Insert(
0,
new ApplicationMenuItem(
GrapesJsMenus.Home,
l["Menu:Home"],
"/",
icon: "fas fa-home",
order: 0
)
);
// ADD this
context.Menu.Items.Insert(
1,
new ApplicationMenuItem(
GrapesJsMenus.CmsTest.Create,
l["Create"],
"~/my-cms-page-create",
icon: "fas fa-home",
order: 0
)
);
// ADD this
context.Menu.Items.Insert(
2,
new ApplicationMenuItem(
GrapesJsMenus.CmsTest.Update,
l["Update"],
"~/my-cms-page-update",
icon: "fas fa-home",
order: 0
)
);
if (MultiTenancyConsts.IsEnabled)
{
administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 3);
}
else
{
administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName);
}
administration.SetSubItemOrder(IdentityMenuNames.GroupName, 4);
administration.SetSubItemOrder(SettingManagementMenus.GroupName, 5);
return Task.CompletedTask;
}
}
under Components/Pages/CmsKit
CmsPageCreate.razor
@page "/my-cms-page-create"
@attribute [Authorize(CmsKitAdminPermissions.Pages.Create)]
@using Blazorise.Components
@using Blazorise.Markdown
@using Cb.Abp.GrapesJs.Blazor.Components.CmsKit
@using Microsoft.AspNetCore.Authorization
@using Volo.Abp.AspNetCore.Components.Web
@using Volo.Abp.AspNetCore.Components.Web.Theming.Layout
@using Volo.Abp.BlazoriseUI.Components.ObjectExtending
@using Volo.CmsKit.Admin.Pages
@using Volo.CmsKit.Localization
@using Volo.CmsKit.Permissions
@using Volo.CmsKit.Admin.Web.Pages.CmsKit
@using Volo.Abp.DependencyInjection;
@inherits GrapesJsComponentBase
@inject AbpBlazorMessageLocalizerHelper<CmsKitResource> LH
@* ************************* PAGE HEADER ************************* *@
<PageHeader Title="@L["Pages"]">
</PageHeader>
<Card>
<CardBody>
<Form>
<Validations @ref="@ValidationsRef" Model="@Page" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Title"] *</FieldLabel>
<TextEdit @bind-Text="Page.Title" Autofocus="true">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Slug"] *</FieldLabel>
<Tooltip Text="@L["PageSlugInformation"]">
<TextEdit @bind-Text="Page.Slug" Autofocus="false">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Tooltip>
</Field>
</Validation>
<ExtensionProperties TEntityType="CreatePageInputDto" TResourceType="CmsKitResource" Entity="@Page" LH="@LH" ModalType="ExtensionPropertyModalType.CreateModal" />
</Validations>
<Tabs @bind-SelectedTab="@SelectedTab">
<Items>
<Tab Name="content">@L["Content"]</Tab>
<Tab Name="script">@L["Script"]</Tab>
</Items>
<Content>
<TabPanel Name="content">
<MyCmsContentBuilderComponent @ref="@ContentBuilder" @bind-Value="@Page.Content" @bind-Css="@Page.Style" />
</TabPanel>
<TabPanel Name="script">
<Markdown @bind-Value="@Page.Script" LineNumbers="true" HideIcons="@HideIcons" AutoDownloadFontAwesome="false" UploadImage="false">
<Toolbar>
<MarkdownToolbarButton Action="MarkdownAction.Bold"/>
</Toolbar>
</Markdown>
</TabPanel>
</Content>
</Tabs>
</Form>
</CardBody>
<CardFooter>
<Button Color="Color.Primary" Clicked="@CreatePageAsync">@L["Submit"]</Button>
</CardFooter>
</Card>
CmsPageCreate.razor.cs
using Blazorise;
using Cb.Abp.GrapesJs.Blazor.Components.CmsKit;
using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;
using Volo.CmsKit.Admin.Pages;
namespace Cb.Abp.GrapesJs.Blazor.Components.Pages.CmsKit;
public partial class CmsPageCreate
{
[Inject]
public IPageAdminAppService PageAdminAppService { get; set; } = default!;
[Inject]
public NavigationManager NavigationManager { get; set; } = default!;
public CreatePageInputDto Page { get; set; } = new CreatePageInputDto();
private Validations ValidationsRef = default!;
private readonly string[] HideIcons = ["bold"];
private string SelectedTab = "content";
public MyCmsContentBuilderComponent ContentBuilder { get; set; } = default!;
protected async Task CreatePageAsync()
{
try
{
var content = await ContentBuilder.GetGrapesContent();
Page.Content = content.Html;
Page.Style = content.Css;
if (await ValidationsRef.ValidateAll())
{
await PageAdminAppService.CreateAsync(Page);
}
}
catch (Exception e)
{
await HandleErrorAsync(e);
}
}
}
under Components/Pages/CmsKit
In order to call this - we need to pass the id to url :-|
Please check the following links as I cannot put the code in here anymore due to something crashing right now -.- https://github.com/Chrobyte/abp-grapesjs/blob/master/src/Cb.Abp.GrapesJs.Blazor/Components/Pages/CmsKit/CmsPageUpdate.razor
Last Modification : 9/11/2024 1:47:23 PM
This site uses cookies.
This website uses cookies. Some cookies are technically necessary, others are used to analyze user behavior in order to optimize the offer. You can find an explanation in our Privacy Policy.