嵌套的角度谷歌地图组件不会呈现

问题描述 投票:0回答:2

我正在使用AGM(Angular Google Maps),我想创建一组自己的自定义组件来包装AGM组件,以便在我的应用程序中高度重用。

但是,当我这样做时,标记(在此示例中)似乎不会在地图上呈现,但我没有错误。我想知道这是否与在<ng-content>中嵌套组件有关

有人可以帮忙吗?我有一个stackblitz设置。请使用Slot查看Angular 7 Stackblitz底部的更新。

TLDR:当我有嵌套的自定义组件时,它创建了一个ng-content HTML元素中间人,似乎打破了agm功能。

我的核心组成部分是vmap

@Component({
  selector: "v-map",
  template: `<agm-map flex [latitude]="lat" [longitude]="lng">
                    <ng-content></ng-content>
                    <!--agm-marker [latitude]="lat" [longitude]="lng"></agm-marker-->
                </agm-map>`
})
export class VMapComponent {
  lat: number = 51.678418;
  lng: number = 7.809007;

  constructor(private loader: MapsAPILoader) {
  }
}

请注意,如果我在模板中的agm-marker中进行评论,则会呈现。它只是在ng-content内似乎不起作用。

这是v-map-plots子组件

@Component({
  selector: "v-map-plots",
  template: `<agm-marker *ngFor="let plot of plots" [latitude]="plot.Latitude" [longitude]="plot.Longitude"></agm-marker>`
})
export class VMapPlotsComponent {
  @Input() plots: IPlot[] = [];

  constructor(@Host() private parent: VMapComponent) {
    this.plots.push({ Latitude: 51.678418, Longitude: 7.809007 })
  }
}

这是AGM问题还是Angular问题?这与ng-content有关吗?有办法解决吗?

根据@ Anytoe的评论更新这里是我的用例:

<v-map>
  <v-map-plots [plots]="displayPlots"></v-map-plots>
</v-map>

我的想法是,我可以制作一些可重复使用的地图组件,然后我可以在需要时在我的应用程序中重复使用。

更新2我读到了关于Slot的想法,并认为这可以帮助我,所以设置一个新的Stackblitz for Angular 7和使用插槽但也无法使这个工作

angular google-maps angular-google-maps ng-content
2个回答
1
投票

首先,我在Angular生态系统下工作,我建议你使用ng-content并探索它的所有功能。 Slot标签用于将内容投影到HTML5模板标签中,功能完全相同,但如果您使用Angular,则使用ng-content,因为它更强大,功能更多。

说,我看了你的stackblitz,它说没有MarkerManager的提供者。这意味着在创建AgmsMarkers时,不会实例化MarkerManager提供程序。

我搜索了一下,我看到你用这种方式组成组件,用v-map和v-map-plot,创建​​的顺序是下一个:

1- v-map
   2- v-map-plots
      3- agm-marker
4- agm-map

Angular首先在v-map上创建了投影内容,因此AgmMarker在AgmMap之前创建。这就是MarkerManager没有提供者的原因,因为它是由AgmMap组件创建的。

鉴于这种情况,我简单地做的就是不包装agm-map。我认为它对你要做的事情没有任何影响,因为你可以根据需要在内部组成尽可能多的组件,如下所示:

<agm-map flex [latitude]="lat" [longitude]="lng">
    <v-map-plots></v-map-plots>
</agm-map> 

我为你的stackblitz做了一个展示它的叉子:https://stackblitz.com/edit/angular-7-master-7jvsjr

希望这可以帮助!


0
投票

正如在另一个答案中已经描述的那样,问题在于AGM库的设计使得它不能用于内容投影。当你在你的情况下使用它时,内容元素是在包装它的组件之前创建的,在这种情况下不起作用,因为首先创建agm-marker-elements并且它们需要来自尚未创建的agm-map组件的服务。它是在内容准备好后创建的。

我建议使用另一种解决方案,以便您保持设计。对于此解决方案,您将v-map-plots组件更改为指令,因此它没有任何渲染。这意味着您不需要任何内容​​投影,而只需使用v-map-plots组件中的@ContentChildren装饰器获取所有v-map指令。然后使用指令中的数据渲染agm-map组件中的agm-markersv-map

这是这样的:

@Directive({
  selector: "v-map-plots"
})
export class VMapPlotsDirective {
  plots: IPlot[] = [];

  constructor(@Host() @Inject(forwardRef(() => VMapComponent)) private parent: VMapComponent) {

    this.plots.push({ Latitude: 51.678418, Longitude: 7.809007 })
    console.log("yo", this.plots);
  }
}

@Component({
  selector: "v-map",
  template: `<agm-map flex [latitude]="lat" [longitude]="lng">
              <ng-container *ngFor="let vMapPlotsDirective of vMapPlotsDirectives">
                <agm-marker *ngFor="let plot of vMapPlotsDirective.plots" [latitude]="plot.Latitude" [longitude]="plot.Longitude"></agm-marker>
              </ng-container>
            </agm-map>`
})
export class VMapComponent {
  lat: number = 51.678418;
  lng: number = 7.809007;
  @ContentChildren(VMapPlotsDirective) vMapPlotsDirectives;

  constructor(private loader: MapsAPILoader) {
  }
}

这也是StackBlitz中的一个实现,所以你可以看到它在行动。

© www.soinside.com 2019 - 2024. All rights reserved.