npm package: @ibm-wch-sdk/ng-api
Description: Module to attach inline-edit functionality to an WCH based Angular application.
Author: Dr. Carsten Leue
Latest version: 6.0.524

# ibm-wch-sdk-ng-edit

Module to attach inline-edit functionality to an [WCH](https://www.npmjs.com/package/ibm-wch-sdk-ng) based [Angular](https://angular.io/) application. The library exposes the `WchNgEditModule` module.

## Usage

Install the module via

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

Add the module to your root application

```typescript
@NgModule({
  ...
  imports: [
    ...
    WchNgEditModule.forRoot(environment)
  ],
  ...
})
export class AppModule { }
```

The module exposes the `WchEditService` and the `wchEditable` directive.

## Prereqs

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

## Directive [wchEditable]

The directive attaches inline edit functionality to an element that is managed by [WCH](https://www.npmjs.com/package/ibm-wch-sdk-ng). The implementation in this library only dispatches the actual realization of the inline-edit functionality to a pluggable service provider.

The directive assumes that the [Component](https://angular.io/api/core/Component) contains a `onRenderingContext` property that exposes the `RenderingContext` of the item currently edited. This contract is fulfilled automatically if the component extends [AbstractRenderingComponent](https://www.npmjs.com/package/ibm-wch-sdk-ng#_30d66fd25c62891da799936c1e1454566f3770b753be58d94b5621b01603a546).

The directive requires as a parameter a string identifying the editable property. This string must reference a property on the [Component](https://angular.io/api/core/Component) that has been bound to a field of the content item via a `@RenderingContextBinding` directive. This directive contains the actual selector of the field. Note that this binding is done automatically if the components are generated via the [CLI](https://www.npmjs.com/package/ibm-wch-sdk-cli).

### Example

```html
<div wchEditable="myField">{{renderingContext.elements.myField.value}}</div>
```

assuming the following binding

```typescript
export class MyComponent extends AbstractRenderingComponent {

   @RenderingContextBinding('elements.myField.value')
   myField: string;

}
```

## WchNgEditModule

The module exposes the directives and services. Per default it provides a service that loads the inline edit functionality from the site composer, when registering the module using the `forRoot` method.

* `forRoot(config?)`: the method registers the module and provides a service to load inline edit from the site composer. The location to load the edit script from is configurable via the config script, typically used for local debugging of the script via the `inlineEditUrl` member on the config object. A convenient way to inject this is to add `inlineEditUrl` to your environment object and then inject the environment object.

### Example

```typescript
import { WchNgEditModule } from 'ibm-wch-sdk-ng-edit';


@NgModule({
  ...
  imports: [
    ...
    WchNgEditModule.forRoot(environment),
    ...
  ]
})
export class AppModule {
}
```

## WchEditInfoService

The service allows to find out if an inline edit operation is taking place. Applications might want to stop any background processing during this period to avoid intercepting with the edit operation.

* `onEditing: Observable<boolean>`: the observable that tracks the state of the current inline edit operation. It is a shared observable that dispatches the current state and all subsequent states.

## WchInlineEditService

Service providers implement the `WchInlineEditService` and provide to the module. This service realizes the actual implementation of the inline edit operation.

* `registerComponent(el, accessor, onRenderingContext): Observable<EventTargetLike>`: this method will be invoked by the `[wchEditable]` directive for every editable element in the application. The `el` parameter references the editable DOM element. The `accessor` is string that represents the [Javascript property accessor](#user-content-accessor-expression) into the content items for the editable element. `onRenderingContext` exposes the context of the currently edited item. The method returns an observable of an [event emitter](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-fromEvent). Subscribing to this observable makes the registration active, unsubscribing cancels it. The event emitter is used to listen for edit events.

### Edit events

The following inline edit events are recognized:

* `wchEditStart`: fired when an element enters into inline edit mode. This is used to track this status by the `WchEditInfoService`.
* `wchEditEnd`: fired when an element leaves inline edit mode (no matter whether the edit operation has been canceled or completed). This is used to track this status by the `WchEditInfoService`.

## WchHttpInlineEditService

The default implementation of the `WchInlineEditService`. If the system is in preview mode, then the service lazily loads an inline edit script from a configurable location. Per default this location points to TODO, it can be overridden by the `inlineEditUrl` property on the config object for the module.

### Script requirements

The inline edit script will be loaded via an HTTP request and executed dynamically. It needs to contain an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) that returns a registration object with the following properties:

* `register(el, accessor, onRenderingContext): Handle`: the register method will be called for every editable element, so the implementation of the method can attach the necessary event handlers to the DOM element to make it editable. The method returns a handle that allows to cancel the registration and to attach event handlers to the inline edit process to monitor it. The method receives the DOM element via the `el` parameter and an `accessor` that represents a Javascript property expression for the editable element in the content item. The `onRenderingContext` observable exposes the current context of the rendered item.

#### Handle

The handle needs to conform to one of the signatures of [EventTargetLike](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-fromEvent) from the [RXJS](http://reactivex.io/rxjs/) spec. In addition it can expose a `dispose` method.

* `dispose`: the dispose method on the handle will be invoked to cancel a registration. This happens when the editable element falls out of scope, e.g. because of a page switch or because the application decides to hide it or for any other reason. Implementers need to make sure to unregister all previously registered event handlers.

#### Require

The inline edit script can use a `require` function that is available in its scope to load extra resources or services exposed by the SDK. The following services are available:

* `wch-config`: a configuration object containing URLs for the current tenant
* `wch-info`: the hub configuration exposed to the SDK by the SPA
* `wch-logger`: access to the SDK logging infrastructure. It is suggested to uses the exposed logger instead of console logs.

In addition the `require` function will resolve URLs relative to the URL used to load the script and returns the result as text. All return values are exposed as promises.

Example for accessing the config:

```typescript
const config = require('wch-config');
config.then(c => console.log(c.apiUrl));
```

Example for loading an extra resource:

```typescript
const res = require('./myExtraResource.txt');
res.then(console.log);
```

Example for using the logger:

```typescript
const logger = require('wch-logger');
logger
  .then(logger => logger.get('MyModule'))
  .then(log => log.info('some log output'));
```

## Accessor Expression

Accessor expressions allow to identify the field of a [Content Item](https://developer.ibm.com/customer-engagement/docs/wch/authoring-content/) that the inline edit operation refers to. It is a string in the format of a [Javascript property accessor](https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Operators/Property_Accessors).

### Examples

* `name`: accesses the name attribute of a content item.
* `elements.myText.value`: accesses the value of a single valued element called `myText`.
* `elements.myTexts.values[2]`: accesses the third value of a multi valued element called `myTexts`.