Вложенные угловые компоненты карт Google не отображаются - PullRequest
0 голосов
/ 29 октября 2018

Я использую AGM (Angular Google Maps) и хочу создать набор своих собственных пользовательских компонентов, которые обертывают компоненты AGM для обеспечения возможности повторного использования в моем приложении.

Однако, когда я делаю это, маркеры (в этом примере) не отображаются на карте, но я не получаю ошибок. Интересно, это как-то связано с вложением компонентов в <ng-content>

Кто-нибудь может помочь? У меня есть stackblitz настройки. Пожалуйста, смотрите обновления внизу для Angular 7 Stackblitz, используя Slot.

TLDR: Когда у меня есть вложенные пользовательские компоненты, он создает посредника 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

@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 или угловая проблема? Это связано с ng-content? Есть ли способ обойти это?

Обновление Согласно комментарию @ Anytoe, вот мой вариант использования:

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

Идея заключается в том, что я могу создать несколько повторно используемых компонентов карт, которые затем можно будет повторно использовать в своем приложении, где это необходимо.

Обновление 2 Я читал о слоте и подумал, что это может мне помочь, поэтому настроил новый Stackblitz для Angular 7 и использовал слот, но также не смог заставить это работать

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Как уже описано в другом ответе, проблема в том, что дизайн библиотеки 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 , чтобы вы могли увидеть его в действии.

0 голосов
/ 21 февраля 2019

Прежде всего, если вы работаете в Угловой экосистеме , я бы порекомендовал вам использовать 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-карте, поэтому AgmMarker создается перед AgmMap . По этой причине у MarkerManager нет поставщика, поскольку он создается компонентом AgmMap.

Учитывая эту ситуацию, я бы просто сделал не оборачивая agm-карту . Я думаю, что это не повлияет на то, что вы пытаетесь сделать, так как вы можете создать столько компонентов внутри, сколько захотите, например:

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

Я сделал форк из вашего стекаблица, показывая его: https://stackblitz.com/edit/angular-7-master-7jvsjr

Надеюсь, это поможет!

...