Skip to content

Commit

Permalink
Rich Text Editor | Angular Integration for label provider in nimble-r…
Browse files Browse the repository at this point in the history
…ich-text-editor (#1477)

# Pull Request

## 🤨 Rationale
Issue Link : #1288

Angular Integration for the rich text component label providers to get
localized from the client app when using the rich text component ( For
now only `rich-text-editor` has labels ).

## 👩‍💻 Implementation

Reference PR for implementation: #1360

This PR adds `NimbleLabelProviderRichTextDirective` in nimble-angular.

## 🧪 Testing

- Added autotests for new directives

## ✅ Checklist

<!--- Review the list and put an x in the boxes that apply or ~~strike
through~~ around items that don't (along with an explanation). -->

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.

---------

Co-authored-by: Aagash Raaj <[email protected]>
  • Loading branch information
aagash-ni and AagashRaaj authored Sep 6, 2023
1 parent babc12c commit 27889e4
Show file tree
Hide file tree
Showing 11 changed files with 443 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<nimble-theme-provider [theme]="theme">
<nimble-label-provider-core withDefaults></nimble-label-provider-core>
<nimble-label-provider-rich-text withDefaults></nimble-label-provider-rich-text>
<nimble-label-provider-table withDefaults></nimble-label-provider-table>
<example-header [(theme)]="theme"></example-header>
<div class="router-outlet-wrapper">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N
NimbleAnchorModule, NimbleAnchorButtonModule, NimbleAnchorTabModule, NimbleAnchorTabsModule,
NimbleIconCheckModule, NimbleBannerModule, NimbleAnchorMenuItemModule, NimbleAnchorTreeItemModule } from '@ni/nimble-angular';
import { NimbleLabelProviderCoreModule } from '@ni/nimble-angular/label-provider/core';
import { NimbleLabelProviderRichTextModule } from '@ni/nimble-angular/label-provider/rich-text';
import { NimbleLabelProviderTableModule } from '@ni/nimble-angular/label-provider/table';
import { NimbleMappingTextModule } from '@ni/nimble-angular/mapping/text';
import { NimbleMappingIconModule } from '@ni/nimble-angular/mapping/icon';
Expand Down Expand Up @@ -40,6 +41,7 @@ import { HeaderComponent } from './header/header.component';
ReactiveFormsModule,
NimbleThemeProviderModule,
NimbleLabelProviderCoreModule,
NimbleLabelProviderRichTextModule,
NimbleLabelProviderTableModule,
NimbleTextAreaModule,
NimbleTextFieldModule,
Expand Down
7 changes: 5 additions & 2 deletions angular-workspace/projects/ni/nimble-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,15 @@ Most user-visible strings displayed by Nimble components are provided by the cli

The standard way to use these in Angular (for localized apps using `@angular/localize`) is:
1. Import the label provider module(s) from your app module:
- `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components besides the table
- `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components that do not have a dedicated label provider
- `NimbleLabelProviderRichTextModule` from `@ni/nimble-angular/label-provider/rich-text`: Used for labels for the rich text components
- `NimbleLabelProviderTableModule` from `@ni/nimble-angular/label-provider/table`: Used for labels for the table (and table sub-components / column types)
2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table]WithDefaultsDirective`:
2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table/RichText]WithDefaultsDirective`:
```html
<nimble-theme-provider theme="light">
<nimble-label-provider-core withDefaults></nimble-label-provider-core>
<!-- if using the Nimble rich text components: -->
<nimble-label-provider-rich-text withDefaults></nimble-label-provider-rich-text>
<!-- if using the Nimble table component: -->
<nimble-label-provider-table withDefaults></nimble-label-provider-table>
<router-outlet></router-outlet>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Directive, ElementRef, Renderer2 } from '@angular/core';
import type { LabelProviderRichText } from '@ni/nimble-components/dist/esm/label-provider/rich-text';

import '@angular/localize/init';

/**
* Directive for nimble-label-provider-rich-text which will initialize all of the labels with $localize-tagged strings, for apps
* using @angular/localize.
*/
@Directive({
selector: 'nimble-label-provider-rich-text[withDefaults]'
})
export class NimbleLabelProviderRichTextWithDefaultsDirective {
public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef<LabelProviderRichText>) {
this.elementRef.nativeElement.toggleBold = $localize`:Nimble rich text - toggle bold|:Bold`;
this.elementRef.nativeElement.toggleItalics = $localize`:Nimble rich text - toggle italics|:Italics`;
this.elementRef.nativeElement.toggleBulletedList = $localize`:Nimble rich text - toggle bulleted list|:Bulleted List`;
this.elementRef.nativeElement.toggleNumberedList = $localize`:Nimble rich text - toggle numbered list|:Numbered List`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
import type { LabelProviderRichText } from '@ni/nimble-components/dist/esm/label-provider/rich-text';

export type { LabelProviderRichText };

/**
* Directive to provide Angular integration for the nimble-rich-text label provider.
* To use the Nimble-provided strings declared via $localize, instead use NimbleLabelProviderRichTextWithDefaultsDirective.
*/
@Directive({
selector: 'nimble-label-provider-rich-text'
})
export class NimbleLabelProviderRichTextDirective {
public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef<LabelProviderRichText>) {
}

public get toggleBold(): string | undefined {
return this.elementRef.nativeElement.toggleBold;
}

// Renaming because property should have camel casing, but attribute should not
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('toggle-bold') public set toggleBold(value: string | undefined) {
this.renderer.setProperty(this.elementRef.nativeElement, 'toggleBold', value);
}

public get toggleItalics(): string | undefined {
return this.elementRef.nativeElement.toggleItalics;
}

// Renaming because property should have camel casing, but attribute should not
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('toggle-italics') public set toggleItalics(value: string | undefined) {
this.renderer.setProperty(this.elementRef.nativeElement, 'toggleItalics', value);
}

public get toggleBulletedList(): string | undefined {
return this.elementRef.nativeElement.toggleBulletedList;
}

// Renaming because property should have camel casing, but attribute should not
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('toggle-bulleted-list') public set toggleBulletedList(value: string | undefined) {
this.renderer.setProperty(this.elementRef.nativeElement, 'toggleBulletedList', value);
}

public get toggleNumberedList(): string | undefined {
return this.elementRef.nativeElement.toggleNumberedList;
}

// Renaming because property should have camel casing, but attribute should not
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('toggle-numbered-list') public set toggleNumberedList(value: string | undefined) {
this.renderer.setProperty(this.elementRef.nativeElement, 'toggleNumberedList', value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NimbleLabelProviderRichTextDirective } from './nimble-label-provider-rich-text.directive';
import { NimbleLabelProviderRichTextWithDefaultsDirective } from './nimble-label-provider-rich-text-with-defaults.directive';

import '@ni/nimble-components/dist/esm/label-provider/rich-text';

@NgModule({
declarations: [NimbleLabelProviderRichTextDirective, NimbleLabelProviderRichTextWithDefaultsDirective],
imports: [
CommonModule
],
exports: [NimbleLabelProviderRichTextDirective, NimbleLabelProviderRichTextWithDefaultsDirective]
})
export class NimbleLabelProviderRichTextModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './nimble-label-provider-rich-text.directive';
export * from './nimble-label-provider-rich-text-with-defaults.directive';
export * from './nimble-label-provider-rich-text.module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { computeMsgId } from '@angular/compiler';
import { loadTranslations } from '@angular/localize';
import type { LabelProviderRichText } from '../nimble-label-provider-rich-text.directive';
import { NimbleLabelProviderRichTextModule } from '../nimble-label-provider-rich-text.module';

describe('Nimble LabelProviderRichText withDefaults directive', () => {
@Component({
template: `
<nimble-label-provider-rich-text withDefaults #labelProvider>
</nimble-label-provider-rich-text>
`
})
class TestHostComponent {
@ViewChild('labelProvider', { static: true }) public labelProvider: ElementRef<LabelProviderRichText>;
}

let labelProvider: LabelProviderRichText;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleLabelProviderRichTextModule, CommonModule]
});
loadTranslations({
[computeMsgId('Bold', 'Nimble rich text - toggle bold')]: 'Translated Bold',
[computeMsgId('Italics', 'Nimble rich text - toggle italics')]: 'Translated Italics',
[computeMsgId('Bulleted List', 'Nimble rich text - toggle bulleted list')]: 'Translated Bulleted List',
[computeMsgId('Numbered List', 'Nimble rich text - toggle numbered list')]: 'Translated Numbered List',
});
const fixture = TestBed.createComponent(TestHostComponent);
const testHostComponent = fixture.componentInstance;
labelProvider = testHostComponent.labelProvider.nativeElement;
fixture.detectChanges();
});

it('applies translated values for each label', () => {
expect(labelProvider.toggleBold).toBe('Translated Bold');
expect(labelProvider.toggleItalics).toBe('Translated Italics');
expect(labelProvider.toggleBulletedList).toBe('Translated Bulleted List');
expect(labelProvider.toggleNumberedList).toBe('Translated Numbered List');
});
});
Loading

0 comments on commit 27889e4

Please sign in to comment.