Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add attribute changed callback to l tile layer wms #57

30 changes: 27 additions & 3 deletions src/l-tile-layer-wms.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,28 @@ import { layerConnected } from "./events.js";
import { htmlAttribute, optional, parse, partial } from "./parse.js";

class LTileLayerWMS extends LLayer {
static get observedAttributes() {
return ["options"];
}

constructor() {
super();
this.layer = null;
}

connectedCallback() {
this.initLayer();
}

attributeChangedCallback(name, oldValue, newValue) {
if (name === "options" && oldValue !== newValue) {
if (this.isConnected) {
this.reloadLayer();
}
}
}

initLayer() {
const urlTemplate = parse(htmlAttribute("url-template"), this);

const name = this.getAttribute("name");
Expand Down Expand Up @@ -47,22 +63,30 @@ class LTileLayerWMS extends LLayer {
};

// Pane options
const paneOptions = {}
const paneOptions = {};
// Support <l-pane> parent element
if (this.parentElement.tagName.toLowerCase() === "l-pane") {
paneOptions["pane"] = this.parentElement.getAttribute("name")
paneOptions["pane"] = this.parentElement.getAttribute("name");
}

this.layer = tileLayer.wms(urlTemplate, {
...standardOptions,
...nonStandardOptions(),
...paneOptions
...paneOptions,
});
const event = new CustomEvent(layerConnected, {
detail: { name, layer: this.layer },
bubbles: true,
});
this.dispatchEvent(event);
}

reloadLayer() {
if (this.layer) {
this.layer.remove();
}
this.initLayer();
}
}

export default LTileLayerWMS;
76 changes: 76 additions & 0 deletions src/l-tile-layer-wms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,79 @@ it("should handle invalid JSON in the options attribute gracefully", () => {
const expected = tileLayer.wms(urlTemplate, { layers: "example layer ere" });
expect(actual).toEqual(expected);
});

it("should reload the layer when the options attribute changes", async () => {
const urlTemplate = "http://example.com/wms";
const initialOptions = JSON.stringify({ height: 101, bbox: "coords ere" });
const updatedOptions = JSON.stringify({ height: 202, bbox: "new coords" });

const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example layer ere");
el.setAttribute("options", initialOptions);

let layerConnectedEventEmittedCount = 0;
let promise = new Promise((resolve) => {
el.addEventListener(layerConnected, (ev) => {
layerConnectedEventEmittedCount += 1;
resolve(ev.detail);
});
});

document.body.appendChild(el);

// Wait for the initial layer to be created
let detail = await promise;
expect(detail.layer.options.height).toBe(101);
expect(detail.layer.options.bbox).toBe("coords ere");

// Change the options attribute
promise = new Promise((resolve) => {
el.addEventListener(layerConnected, (ev) => {
resolve(ev.detail);
});
});

// Update the options attribute
el.setAttribute("options", updatedOptions);

// Wait for the layer to reload
detail = await promise;
expect(detail.layer.options.height).toBe(202);
expect(detail.layer.options.bbox).toBe("new coords");
expect(layerConnectedEventEmittedCount).toBe(2); // initial layer creation + reload
});

it("should not reload the layer when non-options attributes are changed", async () => {
const urlTemplate = "http://example.com/wms";
const initialOptions = JSON.stringify({ height: 101, bbox: "coords ere" });

const el = document.createElement("l-tile-layer-wms");
el.setAttribute("url-template", urlTemplate);
el.setAttribute("layers", "example layer ere");
el.setAttribute("options", initialOptions);

let layerConnectedEventEmittedCount = 0;
let promise = new Promise((resolve) => {
el.addEventListener(layerConnected, (ev) => {
layerConnectedEventEmittedCount += 1;
resolve(ev.detail);
});
});

document.body.appendChild(el);

// Wait for the initial layer to be created
let detail = await promise;
expect(detail.layer.options.height).toBe(101);
expect(detail.layer.options.bbox).toBe("coords ere");

// Update the a different attribute to options
el.setAttribute("a-different-attribute", "with different value");

// Give the layer a chance to reload
detail = await promise;
expect(detail.layer.options.height).toBe(101);
expect(detail.layer.options.bbox).toBe("coords ere");
expect(layerConnectedEventEmittedCount).toBe(1); // initial layer creation only
});