Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ import { NgxSummernoteModule } from 'ngx-summernote';
export class AppModule { }
```

Use `[ngxSummernote]` directive on an element to init Summernote editor:
Use `ngxSummernote` directive on an element to init Summernote editor:

```html
<div [ngxSummernote]></div>
<div ngxSummernote></div>
```

You may also configure Summernote with your own config:
Expand Down Expand Up @@ -92,6 +92,48 @@ export class AppComponent implements OnInit {

See Summernote available initialization options [here](https://summernote.org/deep-dive/#initialization-options).

You can also provide a global config (using the format from above) that will be used for all instances of ngx-summernote.
This global config can still be overridden for specific instances with a custom config like described above.

There are two options to provide a global config:

1) Using the injection token
```typescript
{
provide: NGX_SUMMERNOTE_CONFIG,
useValue: config,
}
```

2) Using the provide function
```typescript
provideNgxSummerNodeConfig(config)
```

If you want to use either of those options, you have to include them in the providers array of your module.
```typescript
import { NgxSummernoteModule, provideNgxSummerNodeConfig, SummernoteOptions } from 'ngx-summernote';

const config: SummernoteOptions = {...} // Your config

@NgModule({
...
providers: [
// Provide global config using either of these two options:
// 1) The token 'NGX_SUMMERNOTE_CONFIG'
{
provide: NGX_SUMMERNOTE_CONFIG,
useValue: config,
}
// 2) The function 'provideNgxSummerNodeConfig'
provideNgxSummerNodeConfig(config)
]
...
})
export class AppModule {
}
```

## Viewer

Use `[ngxSummernoteView]` directive on an element to set innerHTML of an element:
Expand Down
1 change: 1 addition & 0 deletions projects/ngx-summernote/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public_api';
6 changes: 6 additions & 0 deletions projects/ngx-summernote/src/lib/ngx-summernote.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { InjectionToken } from '@angular/core';
import { SummernoteOptions } from './summernote-options';

export const NGX_SUMMERNOTE_CONFIG = new InjectionToken<SummernoteOptions>(
'NGX_SUMMERNOTE_CONFIG'
);
59 changes: 37 additions & 22 deletions projects/ngx-summernote/src/lib/ngx-summernote.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import {
ElementRef,
EventEmitter,
forwardRef,
Inject,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Optional,
Output
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
Expand All @@ -17,6 +19,7 @@ import { map } from 'rxjs/operators';

import { SummernoteOptions } from './summernote-options';
import { codeBlockButton } from './code-block.button';
import { NGX_SUMMERNOTE_CONFIG } from './ngx-summernote.config';

declare var $;

Expand All @@ -35,21 +38,7 @@ export class NgxSummernoteDirective
implements ControlValueAccessor, OnInit, OnDestroy, OnChanges {
@Input() set ngxSummernote(options: SummernoteOptions) {
if (options) {
if (!options.buttons) {
options.buttons = {};
}

options.callbacks = {
...options.callbacks,
onImageUpload: files => this.uploadImage(files),
onMediaDelete: files =>
this.mediaDelete.emit({ url: $(files[0]).attr('src') })
};

// add custom buttons
options.buttons.codeBlock = codeBlockButton;

Object.assign(this._options, options);
this.setOptionsFromConfig(options);
}
}

Expand Down Expand Up @@ -86,7 +75,8 @@ export class NgxSummernoteDirective
constructor(
private el: ElementRef,
private zone: NgZone,
private http: HttpClient
private http: HttpClient,
@Optional() @Inject(NGX_SUMMERNOTE_CONFIG) private summerNoteOptions: SummernoteOptions
) {
const element: any = el.nativeElement;

Expand All @@ -100,6 +90,10 @@ export class NgxSummernoteDirective
// this._$element = <any>$(element);

this.zone = zone;

if (this.summerNoteOptions) {
this.setOptionsFromConfig(this.summerNoteOptions);
}
}

ngOnInit() {
Expand Down Expand Up @@ -212,7 +206,7 @@ export class NgxSummernoteDirective
}

this._$element.on('summernote.init', function () {
setTimeout(function () {
setTimeout(function() {
self.updateModel();
}, 0);
});
Expand All @@ -222,21 +216,21 @@ export class NgxSummernoteDirective
contents,
$editable
) {
setTimeout(function () {
setTimeout(function() {
self.updateModel(contents);
}, 0);
});

this._$element.on('summernote.blur', function () {
setTimeout(function () {
this._$element.on('summernote.blur', function() {
setTimeout(function() {
self.onTouched();
self.blur.emit();
}, 0);
});

if (this._options.immediateAngularModelUpdate) {
this._editor.on('keyup', function () {
setTimeout(function () {
this._editor.on('keyup', function() {
setTimeout(function() {
self.updateModel();
}, 0);
});
Expand Down Expand Up @@ -369,4 +363,25 @@ export class NgxSummernoteDirective
reader.onerror = error => console.error(error);
}
}

/**
* Initialize the editor options with the provided summernote config.
*/
private setOptionsFromConfig(options: SummernoteOptions) {
if (!options.buttons) {
options.buttons = {};
}

options.callbacks = {
...options.callbacks,
onImageUpload: files => this.uploadImage(files),
onMediaDelete: files =>
this.mediaDelete.emit({ url: $(files[0]).attr('src') })
};

// add custom buttons
options.buttons.codeBlock = codeBlockButton;

Object.assign(this._options, options);
}
}
4 changes: 2 additions & 2 deletions projects/ngx-summernote/src/lib/ngx-summernote.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { NgxSummernoteDirective } from './ngx-summernote.directive';
import { NgxSummernoteViewDirective } from './ngx-summernote-view.directive';

Expand All @@ -14,6 +14,6 @@ import { NgxSummernoteViewDirective } from './ngx-summernote-view.directive';
})
export class NgxSummernoteModule {
public static forRoot(): ModuleWithProviders<NgxSummernoteModule> {
return {ngModule: NgxSummernoteModule, providers: []};
return { ngModule: NgxSummernoteModule, providers: [] };
}
}
9 changes: 9 additions & 0 deletions projects/ngx-summernote/src/lib/ngx-summernote.providers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SummernoteOptions } from './summernote-options';
import { NGX_SUMMERNOTE_CONFIG } from './ngx-summernote.config';

export function provideNgxSummerNodeConfig(config: Partial<SummernoteOptions>) {
return {
provide: NGX_SUMMERNOTE_CONFIG,
useValue: config
};
}
2 changes: 1 addition & 1 deletion projects/ngx-summernote/src/lib/summernote-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface SummernoteOptions {
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
},
};
toolbar?: any[];
fontNames?: string[];
callbacks?: any;
Expand Down
5 changes: 5 additions & 0 deletions projects/ngx-summernote/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
export * from './lib/ngx-summernote.directive';
export * from './lib/ngx-summernote-view.directive';
export * from './lib/ngx-summernote.module';

export { SummernoteOptions } from './lib/summernote-options';
export { NGX_SUMMERNOTE_CONFIG } from './lib/ngx-summernote.config';
export { provideNgxSummerNodeConfig } from './lib/ngx-summernote.providers';

export * from './lib/code-block.button';
2 changes: 1 addition & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ <h3>Code</h3>
<div *ngIf="!html || html === ''">
Required
</div>
</ng-container>
</ng-container>
88 changes: 84 additions & 4 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,80 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { NgxSummernoteModule } from 'ngx-summernote';

import { AppComponent } from './app.component';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgxSummernoteModule, provideNgxSummerNodeConfig, SummernoteOptions } from 'ngx-summernote';

declare var $;

function customButton(context) {
const ui = $.summernote.ui;
const button = ui.button({
contents: '<i class="note-icon-magic"></i> Hello',
tooltip: 'Custom button',
container: '.note-editor',
className: 'note-btn',
click: function() {
context.invoke('editor.insertText', 'Hello from test btn!!!');
}
});
return button.render();
}

const ngxSummerNoteConfig: SummernoteOptions = {
airMode: false,
popover: {
table: [
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']]
],
image: [
['image', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']]
],
link: [['link', ['linkDialogShow', 'unlink']]],
air: [
[
'font',
[
'bold',
'italic',
'underline',
'strikethrough',
'superscript',
'subscript',
'clear'
]
]
]
},
height: 200,
uploadImagePath: '/api/upload',
toolbar: [
['misc', ['codeview', 'undo', 'redo', 'codeBlock']],
[
'font',
[
'bold',
'italic',
'underline',
'strikethrough',
'superscript',
'subscript',
'clear'
]
],
['fontsize', ['fontname', 'fontsize', 'color']],
['para', ['style0', 'ul', 'ol', 'paragraph', 'height']],
['insert', ['table', 'picture', 'link', 'video', 'hr']],
['customButtons', ['testBtn']]
],
buttons: {
testBtn: customButton
}
};

@NgModule({
declarations: [
Expand All @@ -17,7 +87,17 @@ import { HttpClientModule } from '@angular/common/http';
NgxSummernoteModule,
HttpClientModule
],
providers: [],
providers: [
// Provide global config either using
// 1) The token 'NGX_SUMMERNOTE_CONFIG'
// {
// provide: NGX_SUMMERNOTE_CONFIG,
// useFactory: ngxSummerNoteConfigFactory,
// }
// 2) The function 'provideNgxSummerNodeConfig'
provideNgxSummerNodeConfig(ngxSummerNoteConfig)
],
bootstrap: [AppComponent]
})
export class AppModule { }
export class AppModule {
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
]
}
}
}
}