Select to view content in your preferred language

Popup header can't be removed in arcgis javascript API 4.28

2646
19
11-16-2023 04:09 AM
SoulaimaneBenmessaoud
New Contributor

I would like to remove the header of the popup, but it is not possible to achieve this by overriding the CSS class directly. This limitation arises because the header is wrapped within a shadow root, as implemented by the calcite components. I am using arcgis javascript API version 4.28.9

SoulaimaneBenmessaoud_0-1700136211458.png

SoulaimaneBenmessaoud_1-1700136275097.png

 

Tags (2)
19 Replies
ViktorSafar
Frequent Contributor

Thanks.

I am sorry but having a post render procedure remove the header is absolutely not a viable solution. We are building commercial systems, this kind of behaviour is not acceptable.

Would the JS API team be opened to adding an API for us to manipulate the header just like we can manipulate the content? Or, regarding those building the popup content from scratch like we are, all we really need is the ability to hide the header one way or another. This had basically worked for years but got broken in 4.28 when the popup was revamped to use calcite.

0 Kudos
JoelBennett
MVP Regular Contributor

Attached is that simplistic test I mentioned earlier.  It has to be run over https (i.e. from a web server and not from a local machine via file: protocol).  Maybe it'll help somehow.

0 Kudos
ViktorSafar
Frequent Contributor

Hi @JoelBennett  - thanks, that example works nicely. However, the same approach does not work when the packages are installed locally and a framework is used - which, I would argue, is the way most applications using ESM are written.

Here is a super simple repro: https://github.com/viktor-safar-geodata/popup-header-problem

I do not have enough knowledge of the JS ecosystem to describe how this is connected. In your "ESM test" solution the problem does not occur as the resourceUrl property is populated. However, in a framework solution, that property is empty resulting in the below error.

popup-chunks-problem-simple-ESM-solution-working.png

ViktorSafar_0-1702929798619.png

 

0 Kudos
ViktorSafar
Frequent Contributor

We have a project on 4.24 where the popup header is outside the shadow DOM while in 4.28 it is inside the shadow DOM. 

ViktorSafar_1-1700479112778.png

 

It appears that an API to customize the popup header might be missing, similar to the API to customize the content.

0 Kudos
Justin_Greco
Frequent Contributor

At 4.28 the popup was refactored to use the Calcite Design System.

https://developers.arcgis.com/javascript/latest/release-notes/#popup-design-updates

0 Kudos
MatiasTonelli1
Emerging Contributor

Hello everyone, I'm having the same problem, the footer also appears and this makes the popup look very bad and altered, but I never added it. This solution is not working for me, any alternative?

example.png

0 Kudos
Justin_Greco
Frequent Contributor

You can modify the style of the shadow DOM, but only after the popup is visible.  The only problem is once its visible, the container hasn't loaded yet.  I put in a 200ms timeout, but it flashes the header real quick, but it will be hidden for all the other times the popup opens.

reactiveUtils
  .whenOnce(() => view.popup?.visible)
  .then(() => {
    setTimeout(() => {
      view.popup.container
        .querySelector(".esri-features__content-feature")
        .shadowRoot.querySelector("calcite-panel")
        .shadowRoot.querySelector(".header").style.display = "none";
    }, 200);
  });

 

0 Kudos
Justin_Greco
Frequent Contributor

Looks like this might be coming in the February release of 4.29, I noticed this in the CHANGELOG for the next version "Added new VisibleElements to the Popup: actionBar, collapseButton, heading, spinner"

I tested this code on the next version and the popup header does not appear:

  const view = new MapView({
    map: webmap,
    container: "viewDiv",
    popup: {
      dockOptions: {
        buttonEnabled: false
      },
      visibleElements: {
        closeButton: false,
        collapseButton: false,
        heading: false,
        actionBar: false
      }
    }
  });  

JustinGreco1_0-1701279571103.png

 

ViktorSafar
Frequent Contributor

Does not seem to work, using @ArcGIS/core@next (which at this stage is v29)

ViktorSafar_0-1702974515187.png

 

0 Kudos
ViktorSafar
Frequent Contributor

I think I figured it out.

We had been making custom popups using 2 features of the built-in popup

  • popup’s content property to render custom content

  • hiding the header/actions bars by overriding the CSS

So when the header moved inside the shadow DOM, we got stuck.

 

After some experiments, it turned out the solution is actually quite simple

  • we do not use the Popup’s content property

  • we instead use the container property to render our custom popup

  • we hide the “entire” default popup by overriding the relevant CSS

 

 

 

import React from 'react'
import { createPortal } from 'react-dom';
import './App.css'
import MapView from '@arcgis/core/views/MapView';
import Map from '@arcgis/core/Map';
import Popup from "@arcgis/core/widgets/Popup.js";

/*
The important stuff

// if you do not do this, the popup will only stay in one (center top) anchor
// if you do this, the anchor will change out of the box as you move around the map
.esri-popup__main-container {  
  height: 0px;
  display: contents !important;
}

.esri-popup__main-container > .esri-widget--panel {
  display: none;
}

on your custom popup, z-index is required to ensure the popup renders over the popup-pointer

*/

const CustomPopup = (props) => {
  return (
    // z-index is required to ensure popup renders over the popup-pointer
    <div style={{ zIndex: 1, backgroundColor: 'white', padding: '20px' }}>
      This is my custom JSX Component popup
    </div>
  )
};

const PopupPortal = ({ mount, children }) => {
  return createPortal(children, mount);
};

const App = () => {

  const popupRoot = document.createElement("div");
  
  React.useEffect(() => {

    const mapView = new MapView({
      container: "mapDiv",
      map: new Map({
        basemap: "streets-navigation-vector"
      })
    });

    mapView.popup = new Popup({
      actions: [],
      container: popupRoot,
    });

    mapView.popupEnabled = false;
    mapView.on("click", (event) => {            
      mapView.openPopup({
        location: event.mapPoint
      });
    });

  }, [])

  return (    
      <div id="mapDiv">  
        <PopupPortal mount={popupRoot}>
          <CustomPopup />
        </PopupPortal>      
      </div>
  )
}

export default App

 

popup-yeah.gif