+
`,
animations: [
trigger('flyInOut', [
@@ -104,6 +133,21 @@ import { NbChatMessageFile } from './chat-message-file.component';
})
export class NbChatMessageComponent {
+ protected readonly builtInMessageTypes: string[] = ['text', 'file', 'map', 'quote'];
+
+ avatarStyle: SafeStyle;
+
+ get _addReplyClass(): boolean {
+ return this._areDefaultStylesEnabled() && this.reply;
+ }
+
+ get _addNotReplyClass(): boolean {
+ return this._areDefaultStylesEnabled() && this.notReply;
+ }
+
+ get _addNoSpaceClass(): boolean {
+ return this._areDefaultStylesEnabled() && !this.message;
+ }
@HostBinding('@flyInOut')
get flyInOut() {
@@ -115,8 +159,6 @@ export class NbChatMessageComponent {
return !this.reply;
}
- avatarStyle: SafeStyle;
-
/**
* Determines if a message is a reply
*/
@@ -193,15 +235,47 @@ export class NbChatMessageComponent {
*/
@Input() type: string;
- constructor(protected domSanitizer: DomSanitizer) { }
+ /**
+ * Data which will be set as custom message template context
+ * @type {any}
+ */
+ @Input() customMessageData: any;
+
+ constructor(protected domSanitizer: DomSanitizer, protected customMessageService: NbCustomMessageService) { }
getInitials(): string {
if (this.sender) {
const names = this.sender.split(' ');
-
return names.map(n => n.charAt(0)).splice(0, 2).join('').toUpperCase();
}
-
return '';
}
+
+ _isBuiltInMessageType(): boolean {
+ // Unset type defaults to "text" type
+ return this.type == null || this.builtInMessageTypes.includes(this.type);
+ }
+
+ _getTemplate(): TemplateRef {
+ const customMessage = this.getCustomMessage(this.type);
+ return customMessage.templateRef;
+ }
+
+ _getTemplateContext(): { $implicit: any, isReply: boolean } {
+ return { $implicit: this.customMessageData, isReply: this.reply };
+ }
+
+ _areDefaultStylesEnabled(): boolean {
+ const customMessageDirective = this.getCustomMessage(this.type);
+ return !customMessageDirective.noStyles;
+ }
+
+ protected getCustomMessage(type: string): NbChatCustomMessageDirective {
+ const customMessageDirective = this.customMessageService.getInstance(type);
+ if (!customMessageDirective) {
+ throw new Error(`nb-chat: Can't find template for custom type '${type}'. ` +
+ `Make sure you provide it in the chat component with *nbCustomMessage='${type}'.`);
+ }
+ return customMessageDirective;
+ }
}
diff --git a/src/framework/theme/components/chat/chat.component.ts b/src/framework/theme/components/chat/chat.component.ts
index 356766318e..ca4c5b96c7 100644
--- a/src/framework/theme/components/chat/chat.component.ts
+++ b/src/framework/theme/components/chat/chat.component.ts
@@ -25,6 +25,7 @@ import { NbComponentOrCustomStatus } from '../component-status';
import { convertToBoolProperty, NbBooleanInput } from '../helpers';
import { NbChatFormComponent } from './chat-form.component';
import { NbChatMessageComponent } from './chat-message.component';
+import { NbCustomMessageService } from './custom-message.service';
/**
* Conversational UI collection - a set of components for chat-like UI construction.
@@ -111,6 +112,75 @@ import { NbChatMessageComponent } from './chat-message.component';
*
* @stacked-example(Chat Sizes, chat/chat-sizes.component)
*
+ * # Custom message types
+ *
+ * Besides built-in message types, you could provide custom ones with their own template to render.
+ * As an example, let's add the `link` message type.
+ *
+ * First, you need to provide a template for the `link` message type:
+ * ```html
+ *
+ * example.com
+ *
+ * ```
+ * Then, add the `nb-chat-message` component with the `link` type:
+ * ```html
+ *
+ * example.com
+ *
+ *
+ * ```
+ *
+ *
+ *
Important!
+ *
+ * Custom chat messages must be defined before the `nb-chat-message`.
+ *
+ *
+ *
+ * Custom message templates could have arbitrary data associated with them. Let's extract hardcoded link
+ * href and text. To pass some data to the custom message template, use the `customMessageData` input
+ * of the `nb-chat-message` component:
+ * ```html
+ * ...
+ *
+ *
+ * ...
+ * ```
+ * When `customMessageData` is set, this object would become a template context and you'll be able
+ * to reference it via `let varName` syntax:
+ * ```html
+ * {{ data.text }}
+ * ```
+ *
+ * That's it, full example will look like this:
+ * ```html
+ *
+ * {{ data.text }}
+ *
+ *
+ *
+ * ```
+ *
+ * If you want to style your custom template from the ground up you could turn off generic message styling
+ * (such as round borders, color, background, etc.) via the `noStyles` input:
+ * ```html
+ *
...
+ * ```
+ * When you decide to use your own styles, the `isReply` property of the custom message template context
+ * would come in handy. This property allows you to determine whether the message is a reply or not.
+ * For example, to change link text color (as replies have a different background):
+ * ```html
+ *
+ * {{ data.label }}
+ *
+ * ```
+ *
+ * Below, you could find a more complex example with multiple custom message types:
+ * @stacked-example(Custom message, chat/chat-custom-message.component)
+ *
* @styles
*
* chat-background-color:
@@ -178,6 +248,9 @@ import { NbChatMessageComponent } from './chat-message.component';
`,
+ providers: [
+ NbCustomMessageService,
+ ],
})
export class NbChatComponent implements OnChanges, AfterContentInit, AfterViewInit {
diff --git a/src/framework/theme/components/chat/chat.module.ts b/src/framework/theme/components/chat/chat.module.ts
index e50192b348..cf2c91969b 100644
--- a/src/framework/theme/components/chat/chat.module.ts
+++ b/src/framework/theme/components/chat/chat.module.ts
@@ -19,6 +19,8 @@ import { NbChatMessageFileComponent } from './chat-message-file.component';
import { NbChatMessageQuoteComponent } from './chat-message-quote.component';
import { NbChatMessageMapComponent } from './chat-message-map.component';
import { NbChatOptions } from './chat.options';
+import { NbChatAvatarComponent } from './chat-avatar.component';
+import { NbChatCustomMessageDirective } from './chat-custom-message.directive';
const NB_CHAT_COMPONENTS = [
NbChatComponent,
@@ -28,6 +30,11 @@ const NB_CHAT_COMPONENTS = [
NbChatMessageFileComponent,
NbChatMessageQuoteComponent,
NbChatMessageMapComponent,
+ NbChatAvatarComponent,
+];
+
+const NB_CHAT_DIRECTIVES = [
+ NbChatCustomMessageDirective,
];
@NgModule({
@@ -39,9 +46,11 @@ const NB_CHAT_COMPONENTS = [
],
declarations: [
...NB_CHAT_COMPONENTS,
+ ...NB_CHAT_DIRECTIVES,
],
exports: [
...NB_CHAT_COMPONENTS,
+ ...NB_CHAT_DIRECTIVES,
],
})
export class NbChatModule {
diff --git a/src/framework/theme/components/chat/custom-message.service.ts b/src/framework/theme/components/chat/custom-message.service.ts
new file mode 100644
index 0000000000..37ffe73809
--- /dev/null
+++ b/src/framework/theme/components/chat/custom-message.service.ts
@@ -0,0 +1,25 @@
+import { Injectable } from '@angular/core';
+
+import { NbChatCustomMessageDirective } from './chat-custom-message.directive';
+
+/**
+ * `NbCustomMessageService` is used to store instances of `NbChatCustomMessageDirective`s which
+ * were provided in the chat component.
+ */
+@Injectable()
+export class NbCustomMessageService {
+
+ protected readonly customMessages = new Map();
+
+ register(type: string, instance: NbChatCustomMessageDirective): void {
+ this.customMessages.set(type, instance);
+ }
+
+ unregister(type: string): boolean {
+ return this.customMessages.delete(type);
+ }
+
+ getInstance(type: string): NbChatCustomMessageDirective | undefined {
+ return this.customMessages.get(type);
+ }
+}
diff --git a/src/framework/theme/public_api.ts b/src/framework/theme/public_api.ts
index e339fdf8d4..4ea739377d 100644
--- a/src/framework/theme/public_api.ts
+++ b/src/framework/theme/public_api.ts
@@ -109,6 +109,8 @@ export * from './components/chat/chat-message-text.component';
export * from './components/chat/chat-form.component';
export * from './components/chat/chat.module';
export * from './components/chat/chat.options';
+export * from './components/chat/chat-avatar.component';
+export * from './components/chat/chat-custom-message.directive';
export * from './components/spinner/spinner.component';
export * from './components/spinner/spinner.directive';
export * from './components/spinner/spinner.module';
diff --git a/src/playground/with-layout/chat/chat-custom-message.component.html b/src/playground/with-layout/chat/chat-custom-message.component.html
new file mode 100644
index 0000000000..ee0ec8cfce
--- /dev/null
+++ b/src/playground/with-layout/chat/chat-custom-message.component.html
@@ -0,0 +1,32 @@
+
+
+
+ {{ data.text }}
+
+
+