Reputation: 1
I have problem regarding uploading image sometimes inside the editor. When I upload image, image is going outside of note-editable div. I saw that some people has same problem but I did not find the solution. Here is the image:
As you can see, the image is outside of note-editable div. I was trying to fix by scss hacks but it's same. Please help me if someone has same issue or know how to fix it. Thank you.
Steps:
When I click on this Image icon, modal will be opened Image Icon
for opening modal
When modal is opened, then I am choosing some picture and modal will be automatically closed and it will show me my page Open modal for adding image
And I put the cursor to add this image after my last one, and as you can see, image is added under the note-editable div. But it needs
to be added in note-editable div. Added image outside of
note-editable div
Here is the my .ts file of summernote component:
@Component({
selector: 'summernote-editor',
templateUrl: './summernote-editor.component.html',
styleUrls: ['./summernote-editor.component.scss'],
encapsulation: ViewEncapsulation.None,
standalone: true,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SummernoteEditorComponent),
multi: true,
},
],
imports: [FormsModule, NgxSummernoteModule],
})
export class SummernoteEditorComponent implements OnChanges, ControlValueAccessor {
constructor() {this.InitSummernote(); }
readonly value = signal(null);
private onChange: Function = () => {};
private onTouched: Function = () => {};
summernoteConfig: any;
ngOnChanges() {
}
handleOnChange(value: any) {
this.onChangedAndTouched(value?.toString());
}
onChangedAndTouched(value: string) {
this.onTouched();
this.onChange(value);
this.writeValue(value);
}
setStateTouched() {
this.onTouched();
}
writeValue(obj: any): void {
this.value.set(obj);
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
private InitSummernote() {
// Summer Note / Description
this.summernoteConfig = {
disableDragAndDrop: true,
// airMode: true,
placeholder: '',
tabsize: 2,
height: '400px',
//uploadImagePath: '/api/upload',
toolbar: [
['style', ['style']],
['undoredo', ['undo', 'redo']],
[
'font',
[
'bold',
'italic',
'underline',
'strikethrough',
'superscript',
'subscript',
'clear',
],
],
['color', ['forecolor']],
['para', ['ul', 'ol']],
['insert', ['table', 'picture', 'link', 'video', 'hr']],
['misc', ['fullscreen', 'codeview']],
['mybutton', ['disableBg', 'enableBg', 'flex', 'imageLink', 'addNote', 'addWarning', 'addTip']],
],
buttons: {
disableBg: GrayBgButton,
flex: flexAlign,
imageLink: ImageLink,
addNote: addNoteButton,
addWarning: addWarningButton,
addTip: addTipButton,
},
styleTags: ['h2', 'h3', 'h4', 'h5', 'p'],
imageAttributes: {
icon: '<i class="note-icon-pencil"/>',
figureClass: 'figureClass',
figcaptionClass: 'captionClass',
captionText: 'Caption Goes Here.',
},
lang: 'en-US',
popover: {
image: [
[
'image',
[
'resizeFull',
'resizeHalf',
'resizeQuarter',
'resizeNone',
],
],
/*['float', ['floatLeft', 'floatRight', 'floatNone']],*/
['remove', ['removeMedia']],
['custom', ['imageAttributes']],
],
},
callbacks: {
onInit: () => {
const editor = $('#summernote')
enableVideoResize(editor);
},
}
};
}
insertImageLink() {
const reader = new FileReader();
const file = $("#imageFile")[0].files[0];
const link = $("#linkUrl").val();
const aNode = document.createElement("a");
const img = document.createElement("img");
if (!link) {
alert('You need to specify anchor link');
return;
}
aNode.target = "_blank";
aNode.href = link;
aNode.appendChild(img);
reader.onload = function (e) {
img.src = e.target.result as string;
// selection
$("#summernote").summernote("editor.saveRange");
$("#summernote").summernote("editor.restoreRange");
$("#summernote").summernote("editor.focus");
$("#summernote").summernote("editor.insertNode", aNode);
// reset
$("#imageFile").val("");
$("#linkUrl").val("");
}
reader.readAsDataURL(file);
this.hideInsertImageLinkModal();
}
hideInsertImageLinkModal() {
$('#imageLinkModal').modal('hide');
}
}
Also here is the HTML code of my parent component where I am calling this summernote component on the bottom:
<div [formGroup]="articleForm">
<div class="modal fade" id="ModalArticle" data-bs-backdrop="static" data-bs-keyboard="true" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<span *ngIf="this.addNew">Add Article</span>
<span *ngIf="!this.addNew">Edit Article</span>
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"
(click)="Close()"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-md-4">
<div class="form-group">
<label for="isPublished">Visibility <span class="asterisks">*</span></label>
<div class="form-check">
<label class="form-check-label" for="isPublished">
<input type="checkbox" class="form-check-input" id="isPublished"
formControlName="isPublished"
[ngClass]="{ 'is-invalid': articleForm.get('isPublished').errors && articleForm.controls['isPublished'].touched}"
[ngClass]="{ 'is-valid': !articleForm.get('isPublished').errors && articleForm.controls['isPublished'].touched}" />
<i *ngIf="articleForm.get('isPublished').value == false"
style="color:rgb(200,200,200)">Article <b>is not published</b></i>
<i *ngIf="articleForm.get('isPublished').value == true"
style="color:rgb(50,50,50)">Article <b>is published</b></i>
</label>
</div>
<div class="form-check">
<label for="isPublic">
<input type="checkbox" class="form-check-input" id="isPublic"
formControlName="isPublic"
[ngClass]="{ 'is-invalid': articleForm.get('isPublic').errors }" />
<i *ngIf="articleForm.get('isPublic').value == false"
style="color:rgb(200,200,200)">Article <b>is not public</b></i>
<i *ngIf="articleForm.get('isPublic').value == true"
style="color:rgb(50,50,50)">Article <b>is public</b></i>
</label>
</div>
<div class="form-check">
<label for="isCortexAllowed">
<input type="checkbox" class="form-check-input" id="isCortexAllowed"
formControlName="isCortexAllowed"
[ngClass]="{ 'is-invalid': articleForm.get('isCortexAllowed').errors }" />
<i *ngIf="articleForm.get('isCortexAllowed').value == false"
style="color:rgb(200,200,200)">Article <b>is not editable by cortex user</b></i>
<i *ngIf="articleForm.get('isCortexAllowed').value == true"
style="color:rgb(50,50,50)">Article <b>is editable by cortex user</b></i>
</label>
</div>
</div>
</div>
<div class="col-xs-12 col-md-4">
<div class="form-group">
<label for="code">Code <span class="asterisks">*</span></label>
<input type="text" maxlength="10" class="form-control" formControlName="code"
[ngClass]="{ 'is-invalid': articleForm.get('code').errors && articleForm.controls['code'].touched }"
[ngClass]="{ 'is-valid': !articleForm.get('code').errors && articleForm.controls['code'].touched}" />
<div *ngIf="articleForm.get('code').errors != null && (articleForm.controls['code'].dirty || articleForm.controls['code'].touched)"
class="invalid-feedback">
<div *ngIf="articleForm.get('code').errors.required">Code is required</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-4">
<div class="form-group">
<label for="kbArticleVersionId">Version <span class="asterisks">*</span></label>
<select class="form-select" formControlName="kbArticleVersionId"
aria-label="Default select example"
[ngClass]="{ 'is-invalid': articleForm.get('kbArticleVersionId').errors && articleForm.controls['kbArticleVersionId'].touched}"
[ngClass]="{ 'is-valid': !articleForm.get('kbArticleVersionId').errors && articleForm.controls['kbArticleVersionId'].touched}">
<option *ngFor="let version of versions" value="{{version.id}}">{{version.name}}
</option>
</select>
</div>
</div>
</div>
<div class="row pt-3">
<div class="col-xs-12 col-md-6">
<div class="form-group">
<label for="subject">Subject <span class="asterisks">*</span></label>
<input type="text" (keyup)="subjectChanged()" maxlength="900" class="form-control"
formControlName="subject"
[ngClass]="{ 'is-invalid': articleForm.get('subject').errors && articleForm.controls['subject'].touched }"
[ngClass]="{ 'is-valid': !articleForm.get('subject').errors && articleForm.controls['subject'].touched}" />
<div *ngIf="articleForm.get('subject').errors && (articleForm.controls['subject'].dirty || articleForm.controls['subject'].touched)"
class="invalid-feedback">
<div *ngIf="articleForm.get('subject').errors.required">Subject is required</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6">
<div class="form-group">
<label for="url">
Url <span class="asterisks">*</span>
<i style="font-size: 12px;">(Url is autogenerated by the subject)</i>
</label>
<input type="text" maxlength="1000" class="form-control" formControlName="url"
[ngClass]="{ 'is-invalid': articleForm.get('url').errors && articleForm.controls['url'].touched}"
[ngClass]="{ 'is-valid': !articleForm.get('url').errors && articleForm.controls['url'].touched}" />
<div *ngIf="articleForm.get('url').errors && (articleForm.controls['url'].dirty || articleForm.controls['url'].touched)"
class="invalid-feedback">
<div *ngIf="articleForm.get('url').errors.required">Url is required</div>
</div>
</div>
</div>
</div>
<div class="row pt-3">
<div class="col-xs-12 col-md-6">
<div class="form-group">
<label for="description">Meta description</label>
<input type="text" maxlength="500" class="form-control" formControlName="description" />
</div>
</div>
<div class="col-xs-12 col-md-6">
<div class="form-group">
<label for="tags">Tags <i style="font-size: 12px;">(Please use the comma , as a
separator)</i></label>
<input type="text" maxlength="500" class="form-control" formControlName="tags" />
</div>
</div>
</div>
<!--CALLING SUMMERNOTE COMPONENT-->
<div class="form-group pt-3">
<label for="body">Body</label>
<summernote-editor formControlName="body"></summernote-editor>
</div>
</div>
<div class="modal-footer">
<button type="button" #closeModal id="closeModal" (click)="Close()" type="button"
data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
<button type="button" class="btn btn-primary" (click)="Save()" label="Create">Save</button>
</div>
</div>
</div>
</div>
And please tell me if you need something else. Thank you so much.
NOTE: Here is the link of GitHub where someone has the same problem but I did not found the solution:
https://github.com/summernote/summernote/issues/2939
Upvotes: 0
Views: 15