Select to view content in your preferred language

Add collapsible Floating Panel at bottom for FeatureTable widget ?

2000
6
01-11-2023 10:57 PM
MayurDodiya
Frequent Contributor

Hi,

I am following tutorial Creating a Map app from here Create a mapping app | Calcite Design System | ArcGIS Developers .

I want to add collapsible floating panel at bottom of page for AttributeTable/FeatureTable widget like below example.

There is calcite-shell-centre-row and not getting where to add in the page to align to the bottom of page. I tried to add inside calcite-shell tag however it is added below view Div, it doesn't fit into the page and added scrollbar to page.

MayurDodiya_1-1673506437386.png

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Calcite Demo</title>
    <style>
      body {
        display: flex;
      }
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
      #headerDiv {
        text-align: center;
        height: 30px;
      }
      .calcite-tutorial {
        --calcite-ui-brand: #0079c1;
        --calcite-ui-brand-hover: #0079c1;
      }

      .calcite-tutorial calcite-chip {
        --calcite-ui-foreground-2: var(--calcite-ui-brand);
        --calcite-ui-text-1: white;
        margin-inline-end: 0.75rem;
      }
      .esri-view .esri-view-surface--inset-outline:focus::after {
        outline: none !important;
      }
    </style>
    <script
      type="module"
      src="https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.esm.js"
    ></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://js.arcgis.com/calcite-components/1.0.0-beta.99/calcite.css"
    />
    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.25/esri/themes/light/main.css"
    />
    <script src="https://js.arcgis.com/4.25/"></script>
  </head>
  <body>
    <script>
      require([
        "esri/Map",
        "esri/WebMap",
        "esri/views/MapView",
        "esri/widgets/Bookmarks",
        "esri/widgets/BasemapGallery",
        "esri/widgets/LayerList",
        "esri/widgets/Legend",
        "esri/widgets/Print",
        "esri/widgets/Home",
        "esri/widgets/ScaleBar",
        "esri/layers/FeatureLayer",
        "esri/symbols/WebStyleSymbol",
        "esri/rest/support/TopFeaturesQuery",
        "esri/rest/support/TopFilter",
      ], (
        Map,
        WebMap,
        MapView,
        Bookmarks,
        BasemapGallery,
        LayerList,
        Legend,
        Print,
        Home,
        ScaleBar,
        FeatureLayer,
        WebStyleSymbol,
        TopFeaturesQuery,
        TopFilter
      ) =>
        (async () => {
          // const map = new Map({
          //   basemap: "streets-vector", // Basemap layer service
          // });

          const layer = new FeatureLayer({
            url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_National_Parks_Annual_Visitation/FeatureServer/0",
            outFields: ["*"],
            renderer: await setRenderer(),
            popupTemplate: createPopupTemplate(),
          });
          const map = new Map({
            basemap: "streets-navigation-vector",
            layers: [layer],
          });
          //   const map = new WebMap({
          //     portalItem: {
          //       id: "210c5b77056846808c7a5ce93920be81",
          //     },
          //   });
          const view = new MapView({
            map: map,
            //center: [-118.805, 34.027], // Longitude, latitude
            //zoom: 13, // Zoom level
            container: "viewDiv", // Div element
            padding: {
              left: 49,
            },
            center: [-120, 45],
            zoom: 3,
          });
          const basemaps = new BasemapGallery({
            view,
            container: "basemaps-container",
          });
          const bookmarks = new Bookmarks({
            view,
            container: "bookmarks-container",
            editingEnabled: true,
          });
          const layerList = new LayerList({
            view,
            selectionEnabled: true,
            container: "layers-container",
          });
          const legend = new Legend({
            view,
            container: "legend-container",
          });
          const print = new Print({
            view,
            container: "print-container",
          });
          const scaleBar = new ScaleBar({
            view: view,
            unit: "dual", // The scale bar displays both metric and non-metric units.
          });
          view.ui.add(scaleBar, {
            position: "bottom-left",
          });
          let homeWidget = new Home({
            view: view,
          });

          view.ui.add(homeWidget, "top-left");
          view.ui.move("zoom", "top-left");
          const layerView = await view.whenLayerView(layer);
          view.when(() => {
            //   map.when(() => {
            let activeWidget;

            const handleActionBarClick = ({ target }) => {
              if (target.tagName !== "CALCITE-ACTION") {
                return;
              }

              if (activeWidget) {
                document.querySelector(
                  `[data-action-id=${activeWidget}]`
                ).active = false;
                document.querySelector(
                  `[data-panel-id=${activeWidget}]`
                ).hidden = true;
              }

              const nextWidget = target.dataset.actionId;
              if (nextWidget !== activeWidget) {
                document.querySelector(
                  `[data-action-id=${nextWidget}]`
                ).active = true;
                document.querySelector(
                  `[data-panel-id=${nextWidget}]`
                ).hidden = false;
                activeWidget = nextWidget;
              } else {
                activeWidget = null;
              }
            };
            document
              .querySelector("calcite-action-bar")
              .addEventListener("click", handleActionBarClick);
            let actionBarExpanded = false;

            document.addEventListener("calciteActionBarToggle", (event) => {
              actionBarExpanded = !actionBarExpanded;
              view.padding = {
                left: actionBarExpanded ? 135 : 45,
              };
            });
          });
          async function setRenderer() {
            const symbol = new WebStyleSymbol({
              name: "park",
              styleName: "Esri2DPointSymbolsStyle",
            });

            const cimSymbol = await symbol.fetchCIMSymbol();
            cimSymbol.data.symbol.symbolLayers[0].size = 24;
            cimSymbol.data.symbol.symbolLayers[1].size = 0;

            return {
              type: "simple",
              symbol: cimSymbol,
            };
          }
          function createPopupTemplate() {
            return {
              title: "{Park}",
              content: [
                {
                  type: "fields",
                  fieldInfos: [
                    {
                      fieldName: "TOTAL",
                      label: "Total visits",
                      format: { digitSeparator: true },
                    },
                    {
                      fieldName: "F2018",
                      label: "2018",
                      format: { digitSeparator: true },
                    },
                    {
                      fieldName: "F2019",
                      label: "2019",
                      format: { digitSeparator: true },
                    },
                    {
                      fieldName: "F2020",
                      label: "2020",
                      format: { digitSeparator: true },
                    },
                  ],
                },
              ],
            };
          }
          const controlVisitedTypeEl = document.getElementById(
            "control-visited-type-el"
          );
          const controlYearEl = document.getElementById("control-year-el");
          const controlCountPerStateEl = document.getElementById(
            "control-count-per-state-el"
          );
          const controlResetEl = document.getElementById("control-reset-el");
          controlVisitedTypeEl.addEventListener(
            "calciteRadioGroupChange",
            async (event) => {
              (orderBy = event.target.value), filterItems();
            }
          );
          controlYearEl.addEventListener(
            "calciteSelectChange",
            async (event) => {
              (year = event.target.value), filterItems();
            }
          );
          controlCountPerStateEl.addEventListener(
            "calciteSliderChange",
            async (event) => {
              (count = event.target.value), filterItems();
            }
          );
          controlResetEl.addEventListener("click", async () => resetFilters());

          const countDefault = 1;
          const orderByDefault = "DESC";
          const yearDefault = "TOTAL";
          let count = countDefault;
          let orderBy = orderByDefault;
          let year = yearDefault;
          async function filterItems() {
            const query = new TopFeaturesQuery({
              topFilter: new TopFilter({
                topCount: count,
                groupByFields: ["State"],
                orderByFields: `${year} ${orderBy}`,
              }),
              orderByFields: `${year} ${orderBy}`,
              outFields: ["State, TOTAL, F2018, F2019, F2020, Park"],
              returnGeometry: true,
              cacheHint: false,
            });

            document.getElementById("result-list").innerHTML = "";
            document.getElementById("result-block").open = true;

            const results = await layer.queryTopFeatures(query);
            graphics = results.features;

            graphics.forEach((result, index) => {
              const attributes = result.attributes;
              const item = document.createElement("calcite-list-item");
              const chip = document.createElement("calcite-chip");
              chip.value = attributes.State;
              chip.slot = "content-end";
              chip.scale = "s";
              chip.innerText = attributes.State;
              item.label = attributes.Park;
              item.value = index;
              item.description = `${attributes[
                yearDefault
              ].toLocaleString()} visitors`;
              item.addEventListener("click", () =>
                resultClickHandler(result, index)
              );
              item.appendChild(chip);
              document.getElementById("result-list").appendChild(item);
            });

            query.orderByFields = [""];
            const objectIds = await layer.queryTopObjectIds(query);
            layerView.filter = { objectIds };

            determineResetActionState();
          }
          function resultClickHandler(result, index) {
            const popup = graphics && graphics[parseInt(index, 10)];
            if (popup) {
              view.popup.open({
                features: [popup],
                location: result.geometry,
              });
              view.goTo(
                {
                  center: [result.geometry.longitude, result.geometry.latitude],
                  zoom: 4,
                },
                { duration: 400 }
              );
            }
          }
          function determineResetActionState() {
            if (
              count !== countDefault ||
              orderBy !== orderByDefault ||
              year !== yearDefault
            ) {
              controlResetEl.removeAttribute("disabled");
              controlResetEl.indicator = true;
            } else {
              controlResetEl.disabled = true;
              controlResetEl.removeAttribute("indicator");
            }
          }
          function resetFilters() {
            count = countDefault;
            orderBy = orderByDefault;
            year = yearDefault;

            const activeRadioGroupItem = document.querySelector(
              `calcite-radio-group-item[value=${orderByDefault}]`
            );
            activeRadioGroupItem.checked = true;
            controlYearEl.value = yearDefault;
            controlCountPerStateEl.value = countDefault;

            filterItems();
          }
          filterItems();
        })());
    </script>
    <calcite-shell content-behind class="calcite-tutorial">
      <div id="#headerDiv" slot="header">
        <!-- <header>
          <h3>ArcGIS Display Map</h3>
        </header> -->
        <calcite-panel heading="ArcGIS Display Map"></calcite-panel>
      </div>

      <calcite-shell-panel
        slot="panel-start"
        position="start"
        detached
        collapse="true"
        detachedHeightScale="s"
      >
        <calcite-action-bar slot="action-bar">
          <calcite-action
            data-action-id="layers"
            icon="layers"
            text="Layers"
          ></calcite-action>
          <calcite-action
            data-action-id="basemaps"
            icon="basemap"
            text="Basemaps"
          ></calcite-action>
          <calcite-action
            data-action-id="legend"
            icon="legend"
            text="Legend"
          ></calcite-action>
          <calcite-action
            data-action-id="bookmarks"
            icon="bookmark"
            text="Bookmarks"
          ></calcite-action>
          <calcite-action
            data-action-id="print"
            icon="print"
            text="Print"
          ></calcite-action>
          <calcite-action
            data-action-id="information"
            icon="filter"
            text="Filter"
          >
          </calcite-action>
        </calcite-action-bar>

        <calcite-panel
          heading="Layers"
          height-scale="l"
          data-panel-id="layers"
          hidden
        >
          <div id="layers-container"></div>
        </calcite-panel>
        <calcite-panel
          heading="Basemaps"
          height-scale="l"
          data-panel-id="basemaps"
          hidden
        >
          <div id="basemaps-container"></div>
        </calcite-panel>
        <calcite-panel
          heading="Legend"
          height-scale="l"
          data-panel-id="legend"
          hidden
        >
          <div id="legend-container"></div>
        </calcite-panel>
        <calcite-panel
          heading="Bookmarks"
          height-scale="l"
          data-panel-id="bookmarks"
          hidden
        >
          <div id="bookmarks-container"></div>
        </calcite-panel>
        <calcite-panel
          heading="Print"
          height-scale="l"
          data-panel-id="print"
          hidden
        >
          <div id="print-container"></div>
        </calcite-panel>
        <calcite-panel
          heading="National Park Visitation"
          data-panel-id="information"
          hidden
        >
          <calcite-block heading="Filters" open>
            <div slot="control">
              <calcite-action
                disabled
                icon="reset"
                id="control-reset-el"
              ></calcite-action>
              <calcite-tooltip
                label="Reset to defaults"
                reference-element="control-reset-el"
                position="bottom"
              >
                Reset to defaults
              </calcite-tooltip>
            </div>
            <calcite-label>
              Data type, per state
              <calcite-radio-group id="control-visited-type-el" width="full">
                <calcite-radio-group-item value="DESC" checked
                  >Most visited</calcite-radio-group-item
                >
                <calcite-radio-group-item value="ASC"
                  >Least visited</calcite-radio-group-item
                >
              </calcite-radio-group>
            </calcite-label>
            <calcite-label>
              Year data to display
              <calcite-select id="control-year-el">
                <calcite-option
                  label="Total of all time"
                  value="TOTAL"
                ></calcite-option>
                <calcite-option label="2018" value="F2018"></calcite-option>
                <calcite-option label="2019" value="F2019"></calcite-option>
                <calcite-option label="2020" value="F2020"></calcite-option>
              </calcite-select>
            </calcite-label>
            <calcite-label>
              Max parks per state
              <calcite-slider
                id="control-count-per-state-el"
                label-ticks
                ticks="1"
                min="1"
                max="5"
              ></calcite-slider>
            </calcite-label>
          </calcite-block>
          <calcite-block collapsible heading="Results" id="result-block">
            <calcite-list id="result-list"></calcite-list>
          </calcite-block>
        </calcite-panel>
      </calcite-shell-panel>

      <div id="viewDiv"></div>

      <calcite-shell-center-row></calcite-shell-center-row>
      <!-- <footer slot="footer">ArcGIS JavaScript Maps SDk for JavaScript</footer> -->
    </calcite-shell>
  </body>
</html>

 

 

6 Replies
KittyHurley
Esri Contributor

Hi @MayurDodiya, the demo screenshot mentioned uses Shell Center Row, however it uses a custom table with styling which has some conflicts with ArcGIS Maps SDK for JavaScript FeatureTable widget.

 

Put together a few Codepen samples with some basic FeatureTable widget functionality. One with the widget with the Create a mapping app tutorial, and the other with a customized table using Shell Center Row, which would need additional styling and functionality to work more cohesively with the FeatureTable widget.

 

For more advanced FeatureTable properties and methods would also recommend checking out some of the fantastic FeatureTable samples available on ArcGIS Maps SDK for JavaScript's site.

 

We're also evaluating our layout components for opportunities to improve in the future. Stay tuned for additional functionality and updates!

0 Kudos
LefterisKoumis
Frequent Contributor

Hello @KittyHurley I just came across this posting and it helped me a lot to place the feature table at the bottom without the CSS hellhole. It would be great if calcite-table would be able read a feature table to populate its headers and rows. It can be done with quite bit of JS loops but it has to be an easier way.

0 Kudos
KittyHurley
Esri Contributor

@LefterisKoumis Calcite is working towards a more advanced table component, building on functionality from the newly released Table component. Stay tuned for more information in the coming months and into 2024, as the efforts are currently in the design phase.

0 Kudos
LefterisKoumis
Frequent Contributor

Thank you. Exactly what I want for Xmas! 😀

0 Kudos
LefterisKoumis
Frequent Contributor

Hello Kitty. Any updates on the calcite table component. Will features from a layer populate a calcite table? 

Thanks.

0 Kudos
KittyHurley
Esri Contributor

@LefterisKoumis No update at this time, other priorities have shifted the advanced table implementation to 2025 or beyond.

0 Kudos