Filter from your page
Declared filters are the inputs the map's author chose to offer a hosting page. They are the one place a value from your page reaches the map's data, so the rule is strict: a name the author did not declare is refused before anything is applied. Press Try an undeclared filter to see it.
What to notice
getFilterSchema()tells you the names, types and operators - build your UI from it.- A list value means "any of"; numbers take
{ low, high }, dates{ from, to }or a relative window such as{ operator: "inLast", count: 30, unit: "days" }. - When a map is published, a filter is declared automatically for every column one of its slicers can reach.
- This page hides every card and still lists each filter's values:
getSlicerValuesanswers for a hidden slicer. - Filters narrow what the map shows; they are not a security boundary between users.
The code
The complete page. Swap in your own publish id, and ask the map's author to add your site to its allowed origins.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Filter from your page - Icon Map Embed API</title>
<link rel="stylesheet" href="https://www.icon-map.com/embed-examples/examples.css"> <!-- demo styling only -->
</head>
<body>
<div class="ex-main">
<div class="ex-side">
<div id="filters">loading...</div>
<h2>Applied</h2>
<pre class="ex-readout" id="applied">{}</pre>
<div class="ex-chips" style="margin-top:10px">
<button id="clear">Clear filters</button>
<button id="bad">Try an undeclared filter</button>
</div>
<pre class="ex-readout" id="error" style="margin-top:8px;color:#ff8a8a"></pre>
</div>
<div id="map"></div>
</div>
<script src="https://www.icon-map.com/js/iconmap-embed/2/iconmap-embed.umd.min.js"></script>
<script>
const el = document.getElementById("map");
const map = IconMapEmbed.embed(el, {
publishId: "pub_...",
// The map is a globe: let this page's own background show in the space around it.
background: "transparent",
chrome: { legend: false, layerControl: false, bookmarksBar: false, tourTransport: false },
// Every card hidden: this page owns the filter UI. (getSlicerValues still answers for a hidden slicer.)
visibility: { visuals: { "chart-continent": false, "slicer-continent": false, "slicer-size": false, "slicer-capital": false } },
events: ["filtersChanged"],
});
map.ready.catch((error) => console.error(error.code, error.message));
const values = {}; // filter name -> Set
(async () => {
// The filters the map's AUTHOR declared. A page can set these and nothing else.
const schema = await map.getFilterSchema();
const host = document.getElementById("filters");
host.textContent = schema.length ? "" : "This map declares no filters.";
// Value lists: from the schema when the author fixed them, else from the slicer on the same column.
const slicers = await map.getSlicers();
for (const filter of schema) {
values[filter.name] = new Set();
let options = filter.values;
const slicer = slicers.find((s) => s.field === filter.column);
if (!options && slicer) options = (await map.getSlicerValues({ slicerId: slicer.id })).values;
host.append(Object.assign(document.createElement("h2"), { textContent: filter.label ?? slicer?.name ?? filter.name }));
const chips = Object.assign(document.createElement("div"), { className: "ex-chips" });
for (const option of options ?? []) {
const chip = Object.assign(document.createElement("button"), { textContent: String(option).replace(/^\d\. /, "") });
chip.onclick = () => {
const set = values[filter.name];
set.has(option) ? set.delete(option) : set.add(option);
chip.classList.toggle("on", set.has(option));
apply();
};
chips.append(chip);
}
host.append(chips);
}
})();
// setFilters replaces every filter value at once; a list means "any of".
function apply() {
const filters = {};
for (const [name, set] of Object.entries(values)) if (set.size) filters[name] = [...set];
return map.setFilters(filters).catch(show);
}
document.getElementById("clear").onclick = () => {
for (const set of Object.values(values)) set.clear();
for (const chip of document.querySelectorAll(".ex-chips button.on")) chip.classList.remove("on");
map.clearFilters();
};
// A name the author did not declare is refused before anything is applied.
document.getElementById("bad").onclick = () => map.setFilters({ salary: [100000] }).catch(show);
function show(error) {
document.getElementById("error").textContent = `${error.code}\n${error.message}`;
}
map.on("filtersChanged", ({ filters, reason }) => {
document.getElementById("error").textContent = "";
document.getElementById("applied").textContent = `${JSON.stringify(filters, null, 1)}\n(${reason})`;
});
</script>
</body>
</html>