npm package: @ibm-wch-sdk/ng-components
Description: Implementation of base components for [WCH](https://www.npmjs.com/package/ibm-wch-sdk-ng) based [Angular](https://angular.io/) applications. These base components implement business logic for commonly used scenarios but do NOT expose any markup. Subclass 
Author: Dr. Carsten Leue
Latest version: 6.0.524

# ibm-wch-sdk-ng-components

Implementation of base components for [WCH](https://www.npmjs.com/package/ibm-wch-sdk-ng) based [Angular](https://angular.io/) applications. These base components implement business logic for commonly used scenarios but do NOT expose any markup. Subclass the components to provide a custom UI layer.

## Usage

Install the module via

```bash
npm install --save ibm-wch-sdk-ng-components
```

## Prereqs

* [ibm-wch-sdk-ng](https://www.npmjs.com/package/ibm-wch-sdk-ng)
* Angular 4.0 or higher (including Angular 5)

## AbstractNavigationComponent

Base class for components that display the site structure of [WCH](https://developer.ibm.com/customer-engagement/watson-content-hub/). The component offers properties that represent an analysis of the site structure for easy consumption, such as the currently selected page, its siblings, children, parents, etc.

### Usage

Create your custom component and inherit from `AbstractNavigationComponent`.

```typescript
import { AbstractNavigationComponent } from 'ibm-wch-sdk-ng-components';

@Component({
  ...
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class NavigationComponent extends AbstractNavigationComponent implements OnInit, OnDestroy {

  constructor(aInjector: Injector) {
    super(aInjector);
  }

  // this seems to be required in order to have AOT recognize the method
  ngOnInit() {
    super.ngOnInit();
  }

  // this seems to be required in order to have AOT recognize the method
  ngOnDestroy() {
    super.ngOnDestroy();
  }

}
```

**Note** that your component has to explicitly override the `OnInit` and `OnDestroy` lifecycle methods. This is required, because the AOT build process does not detect the lifecycle implementation from a base component.

### Properties

The following properties are provided out of the box.

* `onRenderingContext: Observable<RenderingContext>`: `RenderingContext` for the currently selected page
* `onSiblings: Observable<SitePage[]>`: sibilings of the currently selected page
* `onChildren: Observable<SitePage[]>`: children of the currently selected page
* `onBreadcrumb: Observable<SitePage[]>`: breadcrumb trail of the currently selected page
* `onParent: Observable<SitePage>`: parent page of the currently selected page
* `onParents: Observable<SitePage[]>`: siblings of the parent page of the currently selected page

### Methods

The following methods are provided out of the box.

* `getParent: (aPage?: SitePage) => Observable<SitePage>`: parent of an arbitrary page
* `getChildren: (aPage?: SitePage) => Observable<SitePage[]>`: children of an arbitrary page
* `getSiblings: (aPage?: SitePage) => Observable<SitePage[]>`: siblings of an arbitrary page
* `isSelected: (aPage?: SitePage) => Observable<boolean>`: tests if a page is the selected page
* `trackByPageId`: method to be used for a `*ngFor` loop over pages for performance reasons

### Recommendation

Use the `Observable` based properties in your HTML template. You can also use them in the constructor of your custom component to build derived and compound objects using the [RXJS](http://reactivex.io/rxjs/) APIs.

If all state is managed via the `Observable` pattern, the state of your component can only change when any of these observables fires. So we can optimize the change detection process by setting `changeDetection: ChangeDetectionStrategy.OnPush` on the component (see also [Angular OnPush Change Detection and Component Design - Avoid Common Pitfalls](https://blog.angular-university.io/onpush-change-detection-how-it-works/)).

### Example

This sample shows a simple navigation rendering:

```html
  <li class="nav-item" *ngFor='let page of onSiblings | async; trackBy: trackByPageId'>
    <a class="nav-link" [class.active]="isSelected(page) | async"  [routerLink]="page.decodedRoute">{{page.name}}</a>
  </li>
```