嵌套的角度谷歌地图组件无法渲染

时间:2018-10-29 16:06:13

标签: angular google-maps angular-google-maps ng-content

我正在使用AGM(Angular Google Maps),并且想要创建一组自己的自定义组件,这些组件包装了AGM组件以允许在我的应用程序中高度重复使用。

但是,当我这样做时,标记(在此示例中)似乎未呈现在地图上,但是我没有收到任何错误。我想知道这是否与在

中嵌套组件有关

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

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

我的核心要素是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

这是AGM问题还是Angular问题? 这和@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 }) } } 有关吗? 有办法解决吗?

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

ng-content

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

更新2 我了解了有关插槽的信息,并认为这可以为我提供帮助,因此设置一个新的Stackblitz for Angular 7并使用了插槽,但也无法正常工作

2 个答案:

答案 0 :(得分:1)

首先,如果您在 Angular生态系统下工作,我建议您使用 ng-content 并充分利用其所有功能。 Slot标签用于将内容投射到HTML5模板标签中,功能完全相同,但是如果您在Angular下工作,请使用ng-content,因为它功能更强大且用途广泛。

说,我已经看过您的堆叠炸弹了,它说没有MarkerManager的提供者。这意味着创建AgmsMarkers时,不会实例化MarkerManager提供程序。

我进行了一些搜索,发现通过这种方式,您可以通过v-map和v-map-plots组成组件,下一个创建顺序是:

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> 

我用你的堆叠闪电叉显示了它:https://stackblitz.com/edit/angular-7-master-7jvsjr

希望这会有所帮助!

答案 1 :(得分: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中的此实现,因此您可以在实际中看到它。