Text Items

In Blueriq, rich text can be rendered using text items that contain a tree of nodes of three separate types: static, dynamic and style. The latter spans multiple child nodes. This chapter describes how text item nodes are rendered using Angular components.

Node Rendering

The Blueriq TextItem element has a property rootNode to access the root node of the tree. To let the framework select the appropriate component to render, use the bqTextItemNode directive:

<p bqClasses>
  <ng-container [bqTextItemNode]="textItem.rootNode"></ng-container>
</p>

Ensure you import the TextItemModule from @blueriq/angular/textitems from the Angular module that declares your text item component.

Style Nodes

By default, style nodes are rendered using the following template:

<span bqClasses [bqClassesStyles]="node.styles">
  <ng-container *ngFor="let child of node.children" [bqTextItemNode]="child"></ng-container>
</span>

Because of the usage of bqClasses, any style mapping you have registered globally (see styles documentation) will be taken into account. You may include CSS to target these classes in your text item component's styles with the ::ng-deep selector to cross component boundaries.

Component Registration

If using only classes provides insufficient possibilities, you may register a custom component altogether for a certain style. Use TextItemComponents.mapping in an Angular module:

import { NgModule } from '@angular/core';
import { BlueriqCommonModule } from '@blueriq/angular';
import { StyleNode } from '@blueriq/core';
import { TextItemComponents, TextItemModule } from '@blueriq/angular/textitems';
import { CustomStyleNodeComponent } from './custom-style-node/custom-style-node.component'
import { HeaderNodeComponent } from './header-node/header-node.component'

export function hasHeaderStyle(node: StyleNode): boolean {
  return node.styles.has(style => /^header[1-6]$/.test(style));
}

@NgModule({
  // ...
  imports: [
    BlueriqCommonModule,
    TextItemModule,
  ],
  declarations: [
    CustomStyleNodeComponent,
    HeaderNodeComponent,
  ],
  providers: [
    // ...
    TextItemComponents.mapping([
      // use CustomStyleNodeComponent when the node has presentation style 'custom'
      { when: 'custom', useComponent: CustomStyleNodeComponent },

      // use HeaderNodeComponent when the predicate function returns true for the node.
      { when: hasHeaderStyle, useComponent: HeaderNodeComponent },
    ]),
    // ...
  ],
  // ...
})
export class TextRenderingModule {}

The predicate function hasHeaderStyle needs to be an exported function to support AOT compilations.

The style mappings are considered from top-to-bottom, so make sure to register the most specific style regex first. If you need to customize the default template for style nodes, register a component using the regex /./ as last item in the list of mappings.

Continuing above example, the implementation of HeaderNodeComponent may look something like the following:

import { Component } from '@angular/core';
import { StyleNode } from '@blueriq/core';

@Component({
  // ...
  preserveWhitespaces: false,
})
export class HeaderNodeComponent {

  constructor(public node: StyleNode) {}

}

Notice how we obtain access to the actual node to render by injecting it into the constructor. In the component's template, you may again use bqTextItemNode to render the nodes' children.

The component explicitly set preserveWhitespaces to false, to avoid surrounding whitespace to introduce space between text item nodes.

Security Aspects

Dynamic nodes are assumed to contain unsafe data and are therefore escaped through Angular's security mechanisms. Static nodes on the other hand explicitly circumvent Angular's security mechanism, such that any HTML will actually be rendered. Because of these security implications, the framework does not expose the ability to change the component that is used for static and dynamic nodes.

result-matching ""

    No results matching ""