## Visualize KML placemarks

A KML placemark is a feature with associated geometry. LuciadRIA represents it as `KMLPlacemarkFeature`. Visualizing KML data with KML placemarks on a map requires two steps:

1. Create a `KMLModel` by loading a KML file.

2. Use a `KMLLayer` to visualize the model.

``````//First decode the data into a model
const model = new KMLModel(url);

//Create a layer for the model
//The layer visualizes the KML data using the
//styling information provided in the data
const layer = new KMLLayer(model);

//Add the layer to the map

You can also use a `KMLCodec` with any kind of `Store`. For example, you can use a `WFSFeatureStore` to connect to a WFS service returning KML data, or you can implement a custom `Store` that decodes KML data from a string.

The example shows how to visualize KML data using a custom `Store` that reads KML data directly from a string.
``````//StringStore is a read only store that can handle KML data from a string
class StringStore implements Store {

constructor(kmlString: string) {
this.content = kmlString;
this.codec = new KMLCodec();
}

query(_query?: any, _options?: any): Cursor | Promise<Cursor> {
return this.codec.decode({content: this.content});
}
}

//Instantiate the StringStore and configure a FeatureModel with it.
//Where the kmlString contains a text with KML data
const store = new StringStore(kmlString);
const model = new FeatureModel(store);

//Create a layer for the model
const layer = new KMLLayer(model as KMLModel);

//Add the layer to the map

A KML network link is a feature that references a KML or KMZ file on a local or remote network. LuciadRIA represents a KML network link as `KMLNetworkLinkFeature`. When the `KMLCodec` encounters a KML network link while it’s decoding KML data, it emits a `"KMLNetworkLink"` event with the `KMLNetworkLinkFeature` instance. For your convenience, the `KMLModel` propagates this event from the `KMLCodec`. You can register a handler function that consumes this event to create a new `KMLLayer` for the emitted `KMLNetworkLinkFeature`.

 You don’t get instances of `KMLNetworkLinkFeature` when you iterate over a `Cursor` returned by `KMLCodec.decode()`.

## Handle KML ground overlays

A KML ground overlay represents an image overlay draped onto the terrain or floating at a certain altitude. Both the `KMLCodec` and the `KMLModel` emit the `"KMLGroundOverlay"` event with a `KMLGroundOverlayFeature`. You can register a handler function that consumes this event. In the handler, create a layer to visualize the `KMLGroundOverlayFeature` with `createGroundOverlayLayer`, which is exported from the `@luciad/ria/util/KMLUtil` module.

 You do get instances of `KMLGroundOverlayFeature` when you iterate over a `Cursor` returned by `KMLCodec.decode()`.

## Handle KML screen overlays

A KML screen overlay represents an image overlay that you need to add to the view instead of to the map, such as a legend or a logo. Both the `KMLCodec` and the `KMLModel` emit the `"KMLScreenOverlay"` event with a `KMLScreenOverlayFeature`. You can register a handler function that consumes this event. In the handler, create a `HTMLElement` to add the image to.

 You don’t get instances of `KMLScreenOverlayFeature` when you iterate over a `Cursor` returned by `KMLCodec.decode()`.
 See the `KML` sample and Visualizing KML screen overlays to find out how to create an HTML element to add the image of the screen overlay to your view.

### Example of how to handle "KMLNetworkLink", "KMLGroundOverlay", and "KMLScreenOverlay" events

The example shows how to handle the `"KMLNetworkLink"`, `"KMLGroundOverlay",` and `"KMLScreenOverlay"` events.
``````//Register handlers for KML events

(layer.model as KMLModel)?.on("KMLGroundOverlay",
(groundOverlay: KMLGroundOverlayFeature) => onKMLGroundOverlayEvent(groundOverlay, layer));
(layer.model as KMLModel)?.on("KMLScreenOverlay",
(screenOverlay: KMLScreenOverlayFeature) => onKMLScreenOverlayEvent(screenOverlay));
}

//Create a new KML layer that points to the network link's KML data
id: `${id}`, label: `${name}`
});
//Register handlers for newly created KML layer
//Add the layer to the map
}
}

//Handler to consume KMLGroundOverlay event
function onKMLGroundOverlayEvent(groundOverlay: KMLGroundOverlayFeature, parentLayer: KMLLayer) {
const {id, properties, shape} = groundOverlay;
const {icon, name} = properties;

if (shape && shape.bounds && icon && icon.href) {
//Create a new layer with the referenced image
createGroundOverlayLayer(map, groundOverlay, {
layerOptions: {
id: `${id}`, label: `${name}`
}
}).then(layer => {
//Add the layer to the map
});
}
}

//Handler to consume KMLScreenOverlay event
function onKMLScreenOverlayEvent(screenOverlay: KMLScreenOverlayFeature) {
//For an example implementation see ScreenOverlay.tsx in the KML sample.
createOverlay(screenOverlay);
}``````

## Handle the KML data structure

KML data holds features nested in KML containers: KML document and KML folder. LuciadRIA represents those as `KMLDocumentContainer` and `KMLFolderContainer`. Both `KMLDocumentContainer` and `KMLFolderContainer` expose the `children` property with a value that’s an ordered array of all discovered KML features of the types `KMLFolderContainer`, `KMLPlacemarkFeature`, but also the types `KMLNetworkLinkFeature`, `KMLGroundOverlayFeature` and `KMLScreenOverlayFeature`.

When the `KMLCodec` has fully decoded the KML data, it emits a single `"KMLTree"` event with the top-most KML container element. Usually, that’s a `KMLDocumentContainer`. You can register a handler for the `"KMLTree"` event on the `KMLCodec` or `KMLModel` to build a user interface that reflects the hierarchical data structure.

Each `KMLFeature` has common `properties` that you can use for setting the initial states of UI components, for example:

• `open` - specifies whether to show an expanded or collapsed Document or Folder.

• `visibility` - specifies whether to make a feature visible or not when it’s first loaded.

• `snippet` - a short description of the feature.

The example shows how to handle the `"KMLTree"` event to count specific features.
``````// Count all features in folders that contain the "Buildings" text in the "name" property
(kmlLayer.model as KMLModel)?.on("KMLTree", (treeData: KMLFeature[]) => {
const count = treeData.reduce((result: number, feature: KMLFeature) => {
return (feature instanceof KMLFolderContainer &&
feature.properties.name &&
feature.properties.name.indexOf("Buildings") > -1) ?
result + feature.children.length :
result
}, 0);
console.log("Number of features in 'Buildings' folders", count);
});``````
 See the `KML` sample to find out how to create a UI component which displays the data structure of loaded KML.

## Handle KML parsing errors

While decoding KML data, the `KMLCodec` might encounter a problem with the input data. This can be a fatal error from which the `KMLCodec` cannot recover, or an error for which a best effort is done by providing fallback behavior.

When a fatal error occurs, the `KMLCodec` will emit the `"KMLFatalError"` event. You can register a handler function that consumes this event on the `KMLCodec` or the `KMLModel`. Non-fatal errors and fallback behavior that occurred while decoding a `KMLFeature` are reported in the `errorMessages` property.