Adding TinyMCe through richtext input to Crud

This commit is contained in:
2023-02-09 15:33:57 +01:00
parent 4ee649a814
commit 308aec4706
4 changed files with 138 additions and 2 deletions

View File

@@ -20,6 +20,7 @@
"@ngx-formly/bootstrap": "^6.0.0", "@ngx-formly/bootstrap": "^6.0.0",
"@ngx-formly/core": "^6.0.0", "@ngx-formly/core": "^6.0.0",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"@tinymce/tinymce-angular": "^7.0.0",
"ngx-bootstrap-icons": "^1.9.1", "ngx-bootstrap-icons": "^1.9.1",
"ngx-wig": "^15.1.4", "ngx-wig": "^15.1.4",
"rxjs": "~7.5.0", "rxjs": "~7.5.0",
@@ -3383,6 +3384,20 @@
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
"dev": true "dev": true
}, },
"node_modules/@tinymce/tinymce-angular": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-angular/-/tinymce-angular-7.0.0.tgz",
"integrity": "sha512-IKNaG/ihlxE1XCfq6lzULbnsqZO9KNJtlpu5jo6JDJDL9zcFzj/N2A16Kk7rTj1yfmDoB1IXAk/BpMOvgDY8cg==",
"dependencies": {
"tinymce": "^6.0.0 || ^5.5.0",
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": ">=14.0.0",
"@angular/core": ">=14.0.0",
"@angular/forms": ">=14.0.0"
}
},
"node_modules/@tootallnate/once": { "node_modules/@tootallnate/once": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@@ -10978,6 +10993,11 @@
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
"dev": true "dev": true
}, },
"node_modules/tinymce": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.3.1.tgz",
"integrity": "sha512-+oCwXuTxAdJXVJ0130OxQz0JDNsqg3deuzgeUo8X5Vb27EzCJgXwO5eWvCxvkxpQo4oiHMVlM4tUIpTUHufHGQ=="
},
"node_modules/tmp": { "node_modules/tmp": {
"version": "0.0.33", "version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",

View File

@@ -22,6 +22,7 @@
"@ngx-formly/bootstrap": "^6.0.0", "@ngx-formly/bootstrap": "^6.0.0",
"@ngx-formly/core": "^6.0.0", "@ngx-formly/core": "^6.0.0",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"@tinymce/tinymce-angular": "^7.0.0",
"ngx-bootstrap-icons": "^1.9.1", "ngx-bootstrap-icons": "^1.9.1",
"ngx-wig": "^15.1.4", "ngx-wig": "^15.1.4",
"rxjs": "~7.5.0", "rxjs": "~7.5.0",

View File

@@ -7,6 +7,8 @@ import { FormsModule, ReactiveFormsModule} from '@angular/forms';
import { FormlyModule } from '@ngx-formly/core'; import { FormlyModule } from '@ngx-formly/core';
import { FormlyBootstrapModule } from '@ngx-formly/bootstrap'; import { FormlyBootstrapModule } from '@ngx-formly/bootstrap';
import { EditorModule } from '@tinymce/tinymce-angular';
import { CardComponent } from './card/card.component'; import { CardComponent } from './card/card.component';
import { ListComponent } from './list/list.component'; import { ListComponent } from './list/list.component';
import { ArrayTypeComponent } from "./types/array.type"; import { ArrayTypeComponent } from "./types/array.type";
@@ -23,6 +25,7 @@ import { ForeignkeyTypeComponent } from "./types/foreignkey.type";
import { HiddenTypeComponent } from "./types/hidden.type"; import { HiddenTypeComponent } from "./types/hidden.type";
import { DictionaryTypeComponent } from "./types/dictionary.type"; import { DictionaryTypeComponent } from "./types/dictionary.type";
import { DictionaryService } from "./types/dictionary.service"; import { DictionaryService } from "./types/dictionary.service";
import { RichtextTypeComponent } from "./types/richtext.type";
@NgModule({ @NgModule({
@@ -36,7 +39,8 @@ import { DictionaryService } from "./types/dictionary.service";
MultiSchemaTypeComponent, MultiSchemaTypeComponent,
ForeignkeyTypeComponent, ForeignkeyTypeComponent,
HiddenTypeComponent, HiddenTypeComponent,
DictionaryTypeComponent DictionaryTypeComponent,
RichtextTypeComponent
], ],
providers: [ providers: [
JsonschemasService, JsonschemasService,
@@ -63,9 +67,11 @@ import { DictionaryService } from "./types/dictionary.service";
{ name: 'foreign-key', component: ForeignkeyTypeComponent }, { name: 'foreign-key', component: ForeignkeyTypeComponent },
{ name: 'hidden', component: HiddenTypeComponent }, { name: 'hidden', component: HiddenTypeComponent },
{ name: 'dictionary', component: DictionaryTypeComponent }, { name: 'dictionary', component: DictionaryTypeComponent },
{ name: 'richtext', component: RichtextTypeComponent },
] ]
}), }),
FormlyBootstrapModule FormlyBootstrapModule,
EditorModule
], ],
exports: [ exports: [
CardComponent, CardComponent,

View File

@@ -0,0 +1,109 @@
import {Component, OnInit} from "@angular/core";
import { FormlyFieldInput } from "@ngx-formly/bootstrap/input";
@Component({
selector: 'formly-richtext-type',
template: `
<ng-template #labelTemplate>
<label *ngIf="props.label && props.hideLabel !== true" [attr.for]="id" class="form-label">
{{ props.label }}
<span *ngIf="props.required && props.hideRequiredMarker !== true" aria-hidden="true">*</span>
</label>
</ng-template>
<ng-template #inputTemplate>
<editor *ngIf="! this.field.props.disabled"
apiKey="mjk3fhupxy3pitud9iyfqse231zpuuosqedmlgydrjx6mjlo"
[init]="getInitConfig()"
[formControl]="formControl"
[class.is-invalid]="showError"
[formlyAttributes]="field"
[inline]="false"
(onGetContent)="onGetContent($event)"
(onBeforeAddUndo)="onBeforeAddUndo($event)"
></editor>
<div *ngIf="this.field.props.disabled" [innerHTML]="formControl.value" class="form-control">
</div>
</ng-template>
<!-- <div class="mb-3" [class.form-floating]="props.labelPosition === 'floating'" [class.has-error]="showError">-->
<ng-container *ngIf="props.labelPosition !== 'floating'">
<ng-container [ngTemplateOutlet]="labelTemplate"></ng-container>
</ng-container>
<ng-container [ngTemplateOutlet]="inputTemplate"></ng-container>
<div *ngIf="showError" class="invalid-feedback" [style.display]="'block'">
<formly-validation-message [field]="field"></formly-validation-message>
</div>
<small *ngIf="props.description" class="form-text text-muted">{{ props.description }}</small>
<!-- </div>-->
`,
})
export class RichtextTypeComponent extends FormlyFieldInput implements OnInit {
multiline = true;
init_multiline = {
plugins: 'lists image imagetools table code searchreplace autoresize',
menubar: 'edit insert format tools table',
menu: {
edit: { title: 'Edit', items: 'undo redo | cut copy paste | selectall | searchreplace' },
insert: { title: 'Insert', items: 'image link media template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor toc | insertdatetime' },
format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | formats blockformats fontformats fontsizes align lineheight | removeformat' },
tools: { title: 'Tools', items: 'spellchecker spellcheckerlanguage | code wordcount' },
table: { title: 'Table', items: 'inserttable | cell row column | tableprops deletetable' }
},
toolbar: 'undo redo | styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | outdent indent bullist numlist | table image',
statusbar: false,
autoresize_bottom_margin: 0
}
init_singleline = {
plugins: 'autoresize',
menubar: '',
toolbar: 'undo redo | bold italic underline',
statusbar: false,
autoresize_bottom_margin: 0
}
ngOnInit() {
if (this.props.hasOwnProperty('multiline')) {
// @ts-ignore
this.multiline = this.props['multiline']
}
}
getInitConfig() {
let result: { menubar: string, toolbar: string };
if (this.multiline) {
result = this.init_multiline;
} else {
result = this.init_singleline;
}
if (this.field.props.readonly) {
result.menubar = '';
result.toolbar = ''
}
return result;
}
onGetContent(param: any) {
if (!this.multiline) {
const result = param.event.content.match(/<p>(.*)<\/p>/);
if (result) {
param.event.content = result[1];
}
}
}
onBeforeAddUndo(param: any) {
if (!this.multiline) {
if (param.event.level.content.indexOf('</p><p>') > -1) {
param.event.preventDefault()
param.editor.setContent(param.event.level.content.replace('</p><p>', ''));
}
}
}
}