我正在使用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并使用了插槽,但也无法正常工作
答案 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-markers
和v-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中的此实现,因此您可以在实际中看到它。