【问题标题】:Redirect to angular component from Mapbox popup从 Mapbox 弹出窗口重定向到角度组件
【发布时间】:2021-07-05 16:13:43
【问题描述】:

我正在使用 Ionic 和 Angular 开发一个移动应用程序。我在地图上呈现了几个 Mapbox 标记,每个标记都在单击时显示带有自定义内容的弹出窗口。我希望弹出窗口中的按钮将用户重定向到包含有关该特定位置的更多详细信息的页面。我的代码如下:

ionViewWillEnter(){
    this.businessService
    .getBusinessCoords()
    .subscribe(data=>{
      for(const key in data){
        let popup = new mapboxgl.Popup({
          className:'popup-class'
        }).setHTML(
            `<div>
            <img src= ${data[key].profile_picture} width="150">
            <b style="text-align: center;"> ${data[key].name}</b><br>
            <i>${data[key].location.address}</i><br>
            <a id="${key}">Tap to see availble offers!</a>
            </div>
            `
          )
        new mapboxgl.Marker({
          color:"#cc0000",
          draggable: false
        }).setLngLat([data[key].location.coord.lng, data[key].location.coord.lat])
          .setPopup(popup)
          .addTo(this.map);
      }
    })//end subscribe
  }

当然,即用型方法将使用&lt;a&gt;标签的href属性,但我想使用一些特定于Angular的路由方法来路由到显示的每个业务的相应页面在地图上(路线应该取决于 ${key})。到目前为止,我已经尝试在将some-test-class 类添加到&lt;a&gt; 标记后使用document.getElementByClassName("some-test-class")[0].addEventListener('click',()=&gt;{console.log("hello!"});,并按照建议herein the 3rd answer heredocument.getElementById() 类似的东西@ 并且我得到“无法读取未定义的属性'addEventListener' ”。我还尝试了here 列出的第二种方法,但这似乎也不起作用。我还看到了更复杂的解决方案,涉及ComponentFactoryResolverthis question 的公认答案),但在试图解决似乎微不足道的问题之前,我想寻求一个更简单、更-直接方法。或者也许是我之前尝试失败的原因的建议。

【问题讨论】:

    标签: angular typescript ionic-framework mapbox-gl-js ionic5


    【解决方案1】:

    我最终使用here 的第一个答案解决了这个问题。我现在的代码:

    ionViewDidEnter(){
        this.businessService
        .getBusinessCoords()
        .subscribe(data=>{
          for(const key in data){
            const popupContent = document.createElement('div');
            popupContent.innerHTML = `<img src= ${data[key].profile_picture} width="150">
                                      <b style="text-align: center;"> ${data[key].name}</b><br>
                                      <i>${data[key].location.address}</i><br>`;
            const atag = document.createElement('div');
            atag.innerHTML = `<a id="${key}">Tap to see availble offers!</a>`
            popupContent.appendChild(atag); 
            atag.addEventListener('click', (e)=>{
              console.log('Button was clicked' + key);
              this.router.navigateByUrl('/foodrevolution/profile')
            })
            let popup = new mapboxgl.Popup({
            }).setDOMContent(popupContent); 
              
            new mapboxgl.Marker({
              color:"#cc0000",
              draggable: false
            }).setLngLat([data[key].location.coord.lng, data[key].location.coord.lat])
              .setPopup(popup)
              .addTo(this.map);
          }
        })//end subscribe
      }
    

    其中router 的类型为Router,来自@angular/router。即使我使用ionViewWillEnter,这件事似乎也能工作,所以我不确定生命周期钩子的选择是否会有所不同。

    【讨论】:

      【解决方案2】:

      当您的数据使用mapboxgl.Sourcemapboxgl.Layer 时,还有另一个选项。

      1. 将您的数据转换为 GeoJson,以便弹出窗口的动态内容存储在 properties 功能中。
      2. 使用转换后的 GeoJson 数据创建 mapboxgl.Source with type: "geojson"
      3. 使用创建的源和您喜欢的样式创建mapboxgl.Layer
      4. 在您的组件模板中添加一个弹出容器,然后在setDOMContent 方法中引用该容器。请参阅下文了解一些原型。

      这允许您在 Popup 和 Angular(不仅仅是路由)之间进行完全交互。

      <!-- component.html -->
      <div #popupContainer class="popup-container">
        <div *ngIf="popup">
          <img [src]="popup.profile_picture" width="150">
          <b style="text-align: center;">{{ popup.name }}</b><br>
          <i>{{ popup.location.address }}</i><br>
          <a routerLink="/foodrevolution/profile">Tap to see availble offers!</a>
        </div>
      </div>
      
      // component.ts
      @ViewChild("popupContainer") popupContainer: any;
      popup: any;
      
      ionViewDidEnter() {
        this.businessService
          .getBusinessCoords()
          .subscribe((data) => {
            const geoJson = toGeoJson(data);
            this.map.getSource("source-id").setData(geoJson);
          });
        this.map.on("click", "points-layer", (e) => {
          const coordinates = e.features[0].geometry.coordinates.slice();
          this.popup = e.features[0].properties;
          new mapboxgl.Popup()
            .setLngLat(coordinates)
            .setDOMContent(this.popupContainer.nativeElement)
            .addTo(this.map);
        });
      }
      

      GeoJson FeatureCollection 中的单个功能应该或多或少看起来像这样

      {
        type: "Feature",
        geometry: {
          type: "Point",
          coordinates: [
            data[key].location.coord.lng,
            data[key].location.coord.lat
          ]
        },
        properties: {
          key: key,
          name: data[key].name
          // ...
        }
      }
      

      【讨论】:

        【解决方案3】:

        您不能在 ionViewWillEnter 中调用任何 htmlElement,因为未创建视图。 尝试将此代码放入 ionViewDidEnter 中。

        【讨论】:

        • 感谢您的回答,但这不是问题所在。我最终解决了它。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-08
        • 2014-05-15
        • 2021-05-21
        • 1970-01-01
        • 2019-03-18
        相关资源
        最近更新 更多