text:
Add MarkerClusterer to google-maps.

Add support of MarkerClusterer to google-maps.

This feature is definitely one that I'd like to implement. The main issue is addressing loading the separate marker clusterer library and see if there are types we can use, perhaps with DefinitelyTyped.
But it it's something I'd like to do in the future.

The google clustering library is now written in TS.
I would like to see a better solution. As I see Angular, it is best used for applications and in an application, I would see much more appropriate to be able to change the look of clusters.
Something like solution bellow might be the best
<google-map>
  <map-html-marker *mapMarkerClusterer="let cluster of allMarkers"></map-html-marker>
</google-map>

Hello @mbehrlich,
It may help you : https://github.com/DefinitelyTyped/DefinitelyTyped/commits/master/types/google__markerclustererplus

I have MarkerClusterPlus implemented and working in an Angular 9 project. It is not hard, just
import {MarkerClustererOptions} from '@google/markerclustererplus';
import MarkerClusterer from '@google/markerclustererplus';

But, the main problem is that it takes a google.maps.Marker type and returns this type in an event, which makes it a bit of a pain to use the @angular/google-maps InfoWindow - since that takes a MapMarker type. It would be good to see MarkerClustererPlus integrated into @angular/google-maps just to solve that problem - as long as we don't lose anything else of course.

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
Component Markerclusterer
`
/**

Component MarkerClustererPlus
*/
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';

// import { MarkerClustererPlusService } from 'src/app/services/marker-clusterer-plus-service';
@Component({
selector: 'marker-clusterer-plus',
template: <ng-content></ng-content>,
styles: [
]
})
export class MarkerClustererPlusComponent {
mc: MarkerClusterer;
@Input()
googleMaps: GoogleMap;
/**

https://angular.io/api/core/ContentChildren
*/
@ContentChildren("markerElem")
mapMarkers: QueryList;

@Input()
title: string;
@Input()
icon_path: string;
map: google.maps.Map;
options: MarkerClustererOptions;
styles: Array;
@Output()
onLoaded: EventEmitter = new EventEmitter();
constructor() {
this.options = {
  gridSize: 60,
  maxZoom: 20,
  averageCenter: false,
  zoomOnClick: true,
};

this.mc = new MarkerClusterer(null,[],this.options);

}
/**

Apenas quando todos os componentes filhos forem carregados
*/
ngAfterViewInit(){
this.init();
}

init(){
/**
 * Instancia do google.maps.Map
 */
this.map = this.googleMaps._googleMap;

/**
 * Itera sobre ContentChildren
 */
this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
  this.mc.addMarker(mapMarker._marker);
});

/**
 * Altera o titulo passado no input
 */
this.mc.setTitle(this.title || "MarkerCluster");

/**
 *  Personalizando estilo do icone
 * */
this.styles =[
  {
    url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
    height: 52,
    width: 52,
    anchorText: [30,-10],
    textColor: '#fff',
    textSize: 10,
    // backgroundPosition: "4 0",
    // anchorIcon: [0, 0],
    fontWeight: "bold",
  }
];
this.mc.setStyles(this.styles);

/**
 * Mostra o clusterer no mapa e emite evento de carregado
 */
this.mc.setMap(this.map);
this.onLoaded.emit(this.mc);

/**
 * Eventos do Cluster
 */
this.bindEvents();

}
/**

Eventos do Cluster
*/
bindEvents(){
this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
console.log(cluster);
});
}

}
`
App Base
`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';
@Component({
selector: 'maine',
template: `
  <google-map #googleMapRef
    height="100vh"
    width="100%"
    [zoom]="zoom"
    [center]="center"
    (mapClick)="click($event);">

    <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

      <map-marker
        #markerElem
        *ngFor="let marker of cluster.unidades"
        [position]="marker.position"
        [label]="marker.label"
        [title]="marker.title"
        [options]="marker.options"
        (mapClick)="openInfo(markerElem);"
      >
      </map-marker>

    </marker-clusterer-plus>

    <map-info-window>Teste</map-info-window>

  </google-map>

,   styles: [
`
]
})
export class AppComponent implements OnInit, OnChanges {
@ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;
@ViewChild('googleMapRef')
googleMaps : GoogleMap;
@ViewChild('marker-clusterer-plus')
markerClusterer : MarkerClustererPlusComponent;
@Input()
zoom:number = 8;
@Input()
center:google.maps.LatLngLiteral;
@Input()
markers: Array = [];
array_clusteres: Array = [];
constructor(private element: ElementRef) { }
ngOnInit(): void {
navigator.geolocation.getCurrentPosition(position => {
  this.center = {
    lat: position.coords.latitude,
    lng: position.coords.longitude,
  }

  this.loadOptions();

  this.loadDataGeoJson();

});

}
ngAfterViewInit(){
console.log('MaineComponent ngAfterViewInit');
}
loadOptions(){
this.googleMaps._googleMap.setOptions({
  styles: [
    {
      'stylers': [{'visibility': 'on'}]
    },
    {
      'featureType': 'landscape',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
    },
    {
      'featureType': 'water',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
    }
  ]
});

}
loadDataGeoJson(){
/**
 * Carrega o geojson com polygons
 */
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});

/**
 * Callback para monitorar fluxo dos estilos do GeoJson
 */
this.googleMaps.data.setStyle(styleFeature);

let enableMouseClick = false;
let enableMouseOver = false;
let enableMouseOut = false;
/**
 * Applies a gradient style based on the 'census_variable' column.
 * This is the callback passed to data.setStyle() and is called for each row in
 * the data set.  Check out the docs for Data.StylingFunction.
 *
 * @param {google.maps.Data.Feature} feature
 */
function styleFeature(feature) {

  var id = feature.getProperty('id');
  var name = feature.getProperty('name');
  var description = feature.getProperty('description');
  var state = feature.getProperty('state');
  var fillColor = '#131958';
  var fillOpacity = 0.3;
  var zIndex = 1;
  var clickable = 'true';
  var showRow = true; // determine whether to show this shape or not

  var options_default = {
      strokeColor: '#1e76ae', // #ffffff
      strokeOpacity: 0.8,
      strokeWeight: 1.5,
      fillColor: fillColor,
      // fillColor: '#000',
      fillOpacity: fillOpacity,
      // clickable: clickable,
      zIndex: zIndex,
      visible: showRow
  };

  // evento em estado de escuta ocioso/normal

  if (name != undefined) {
    /*remove todos os espaços internos e externos*/// alias = obj.city.name.replace(/\s+/g, '');

    // evento em estado de escuta clicked
    if (state == 'click' && enableMouseClick) {}

    // sem evento em estado de escuta Ocioso
    if (state == 'normal' && enableMouseOut) {

        /* Marcar poligonos com um apelido, levando o nome da cidade*/
        // options_default.alias = name;
        // options_default.description = description;
        feature.setProperty('withInfowindowOpen', false);

    }

    // evento em estado de escuta mouseOver
    if (state == 'hover' && enableMouseOver) {
        // options_default.clickable = false;
        options_default.strokeOpacity = 0.8;
        options_default.strokeColor = '#1e76ae';
        options_default.strokeWeight = 6;
        options_default.fillOpacity = 0.1;
        options_default.zIndex = -1;
    }

  }

  return options_default;

}

/** events **/
// click
this.googleMaps.data.addListener('click', (e)=>{
   // set the hover state so the setStyle function can change the border
   e.feature.setProperty('state', 'click');
   console.log('CLICK REGION', e.feature);
});
// mouseover
this.googleMaps.data.addListener('mouseover', (e)=>{
  // set the hover state so the setStyle function can change the border
  e.feature.setProperty('state', 'hover');
  e.feature.getProperty('NAME');
  // console.log('MOUSEIN REGION', e.feature);
});
// mouseout
this.googleMaps.data.addListener('mouseout', (e)=>{
  // set the hover state so the setStyle function can change the border
  e.feature.setProperty('state', 'normal');
  // console.log('MOUSEOUT REGION', e.feature);
});

}
onMcLoaded(markerClusterer:MarkerClusterer){
this.array_clusteres.push(markerClusterer);
/*Recentraliza mapa de acordo com bounds dos markers*/
this.fitBoundsCluster(markerClusterer);

}
/**

Limpa todos os clusteres do mapa
*/
clearMarkerClusteres(){
this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
mc.clearMarkers();
});
}

/**

Recentraliza mapa de acordo com bounds dos markers
@param markerClusterer
*/
fitBoundsCluster(markerClusterer:MarkerClusterer){

let bounds = new google.maps.LatLngBounds();

this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
  mc.getMarkers().forEach( (m)=>{
    bounds.extend(m.getPosition());
  })
})

this.googleMaps.fitBounds(bounds);

}
openInfo(markerElem: MapMarker,content?:string){
console.log(markerElem);
this.infoWindow.open(markerElem);
}
addMarker() {
const plusLat = ((Math.random() - 0.5) * 10) / 10;
const plusLng = ((Math.random() - 0.5) * 10) / 10;
this.markers.push({
  position: {
    lat: this.center.lat + plusLat,
    lng: this.center.lng + plusLng,
  },
  label: {
    color: 'red',
    text: 'Marker label ' + (this.markers.length + 1),
  },
  title: 'Marker title ' + (this.markers.length + 1),
  options: {
    // animation: google.maps.Animation.BOUNCE
  },
})

}
click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
Component Markerclusterer
`
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';
@Component({
selector: 'marker-clusterer-plus',
template: <ng-content></ng-content>,
styles: [
]
})
export class MarkerClustererPlusComponent
{
mc: MarkerClusterer;
@Input()
googleMaps: GoogleMap;
@ContentChildren("markerElem")
mapMarkers: QueryList;
@Input()
title: string;
@Input()
icon_path: string;
map: google.maps.Map;
options: MarkerClustererOptions;
styles: Array;
@Output()
onLoaded: EventEmitter = new EventEmitter();
constructor() {
this.options = {
  gridSize: 60,
  maxZoom: 20,
  averageCenter: false,
  zoomOnClick: true,
};

this.mc = new MarkerClusterer(null,[],this.options);

}
/**

Wait Full Loaded Children Components
*/
ngAfterViewInit(){
this.init();
}

init(){
this.map = this.googleMaps._googleMap;

this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
  this.mc.addMarker(mapMarker._marker);
});

this.mc.setTitle(this.title || "MarkerCluster");

this.styles =[
  {
    url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
    height: 52,
    width: 52,
    anchorText: [30,-10],
    textColor: '#fff',
    textSize: 10,
    fontWeight: "bold",
  }
];
this.mc.setStyles(this.styles);
this.mc.setMap(this.map);
this.onLoaded.emit(this.mc);
this.bindEvents();

}
bindEvents(){
this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
console.log(cluster);
});
}
}
`
App Base
`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';
@Component({
selector: 'maine',
template: `
  <google-map #googleMapRef
    height="100vh"
    width="100%"
    [zoom]="zoom"
    [center]="center"
    (mapClick)="click($event);">

    <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

      <map-marker
        #markerElem
        *ngFor="let marker of cluster.unidades"
        [position]="marker.position"
        [label]="marker.label"
        [title]="marker.title"
        [options]="marker.options"
        (mapClick)="openInfo(markerElem);"
      >
      </map-marker>

    </marker-clusterer-plus>

    <map-info-window>Teste</map-info-window>

  </google-map>

,   styles: [
`
]
})
export class AppComponent implements OnInit, OnChanges {
@ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;
@ViewChild('googleMapRef')
googleMaps : GoogleMap;
@ViewChild('marker-clusterer-plus')
markerClusterer : MarkerClustererPlusComponent;
@Input()
zoom:number = 8;
@Input()
center:google.maps.LatLngLiteral;
@Input()
markers: Array = [];
array_clusteres: Array = [];
constructor(private element: ElementRef) { }
ngOnInit(): void {
navigator.geolocation.getCurrentPosition(position => {
  this.center = {
    lat: position.coords.latitude,
    lng: position.coords.longitude,
  }

  this.loadOptions();

  this.loadDataGeoJson();

});

}
ngAfterViewInit(){
console.log('MaineComponent ngAfterViewInit');
}
loadOptions(){
this.googleMaps._googleMap.setOptions({
  styles: [
    {
      'stylers': [{'visibility': 'on'}]
    },
    {
      'featureType': 'landscape',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
    },
    {
      'featureType': 'water',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
    }
  ]
});

}
loadDataGeoJson(){
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});
this.googleMaps.data.setStyle(styleFeature);

let enableMouseClick = false;
let enableMouseOver = false;
let enableMouseOut = false;
function styleFeature(feature) {

  var id = feature.getProperty('id');
  var name = feature.getProperty('name');
  var description = feature.getProperty('description');
  var state = feature.getProperty('state');
  var fillColor = '#131958';
  var fillOpacity = 0.3;
  var zIndex = 1;
  var clickable = 'true';
  var showRow = true; // determine whether to show this shape or not

  var options_default = {
      strokeColor: '#1e76ae', // #ffffff
      strokeOpacity: 0.8,
      strokeWeight: 1.5,
      fillColor: fillColor,
      fillOpacity: fillOpacity,
      zIndex: zIndex,
      visible: showRow
  };

  if (name != undefined) {

    if (state == 'click' && enableMouseClick) {}

    if (state == 'normal' && enableMouseOut) {
        feature.setProperty('withInfowindowOpen', false);
    }

    if (state == 'hover' && enableMouseOver) {
        options_default.strokeOpacity = 0.8;
        options_default.strokeColor = '#1e76ae';
        options_default.strokeWeight = 6;
        options_default.fillOpacity = 0.1;
        options_default.zIndex = -1;
    }
  }
  return options_default;
}
  this.googleMaps.data.addListener('click', (e)=>{
   // set the hover state so the setStyle function can change the border
   e.feature.setProperty('state', 'click');
   console.log('CLICK REGION', e.feature);
});

this.googleMaps.data.addListener('mouseover', (e)=>{
  e.feature.setProperty('state', 'hover');
  e.feature.getProperty('NAME');
});

this.googleMaps.data.addListener('mouseout', (e)=>{
  e.feature.setProperty('state', 'normal');
});

}
onMcLoaded(markerClusterer:MarkerClusterer){
this.array_clusteres.push(markerClusterer);
this.fitBoundsCluster(markerClusterer);
}
clearMarkerClusteres(){
this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
mc.clearMarkers();
});
}
fitBoundsCluster(markerClusterer:MarkerClusterer){
let bounds = new google.maps.LatLngBounds();

this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
  mc.getMarkers().forEach( (m)=>{
    bounds.extend(m.getPosition());
  })
})

this.googleMaps.fitBounds(bounds);

}
openInfo(markerElem: MapMarker,content?:string){
this.infoWindow.open(markerElem);
}
addMarker() {
const plusLat = ((Math.random() - 0.5) * 10) / 10;
const plusLng = ((Math.random() - 0.5) * 10) / 10;
this.markers.push({
  position: {
    lat: this.center.lat + plusLat,
    lng: this.center.lng + plusLng,
  },
  label: {
    color: 'red',
    text: 'Marker label ' + (this.markers.length + 1),
  },
  title: 'Marker title ' + (this.markers.length + 1),
  options: {
    // animation: google.maps.Animation.BOUNCE
  },
})

}
click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
Component Markerclusterer
`
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';
@Component({
selector: 'marker-clusterer-plus',
template: <ng-content></ng-content>,
styles: [
]
})
export class MarkerClustererPlusComponent
{
mc: MarkerClusterer;
@Input()
googleMaps: GoogleMap;
@ContentChildren("markerElem")
mapMarkers: QueryList;
@Input()
title: string;
@Input()
icon_path: string;
map: google.maps.Map;
options: MarkerClustererOptions;
styles: Array;
@Output()
onLoaded: EventEmitter = new EventEmitter();
constructor() {
this.options = {
  gridSize: 60,
  maxZoom: 20,
  averageCenter: false,
  zoomOnClick: true,
};

this.mc = new MarkerClusterer(null,[],this.options);

}
/**

Wait Full Loaded Children Components
*/
ngAfterViewInit(){
this.init();
}

init(){
this.map = this.googleMaps._googleMap;

this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
  this.mc.addMarker(mapMarker._marker);
});

this.mc.setTitle(this.title || "MarkerCluster");

this.styles =[
  {
    url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
    height: 52,
    width: 52,
    anchorText: [30,-10],
    textColor: '#fff',
    textSize: 10,
    fontWeight: "bold",
  }
];
this.mc.setStyles(this.styles);
this.mc.setMap(this.map);
this.onLoaded.emit(this.mc);
this.bindEvents();

}
bindEvents(){
this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
console.log(cluster);
});
}
}
`

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
Component Markerclusterer
`
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';
@Component({
selector: 'marker-clusterer-plus',
template: <ng-content></ng-content>,
styles: [
]
})
export class MarkerClustererPlusComponent
{
mc: MarkerClusterer;
@Input()
googleMaps: GoogleMap;
@ContentChildren("markerElem")
mapMarkers: QueryList;
@Input()
title: string;
@Input()
icon_path: string;
map: google.maps.Map;
options: MarkerClustererOptions;
styles: Array;
@Output()
onLoaded: EventEmitter = new EventEmitter();
constructor() {
this.options = {
  gridSize: 60,
  maxZoom: 20,
  averageCenter: false,
  zoomOnClick: true,
};

this.mc = new MarkerClusterer(null,[],this.options);

}
/**

Wait Full Loaded Children Components
*/
ngAfterViewInit(){
this.init();
}

init(){
this.map = this.googleMaps._googleMap;

this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
  this.mc.addMarker(mapMarker._marker);
});

this.mc.setTitle(this.title || "MarkerCluster");

this.styles =[
  {
    url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
    height: 52,
    width: 52,
    anchorText: [30,-10],
    textColor: '#fff',
    textSize: 10,
    fontWeight: "bold",
  }
];
this.mc.setStyles(this.styles);
this.mc.setMap(this.map);
this.onLoaded.emit(this.mc);
this.bindEvents();

}
bindEvents(){
this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
console.log(cluster);
});
}
}
`
App Base
`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';
@Component({
selector: 'maine',
template: `
  <google-map #googleMapRef
    height="100vh"
    width="100%"
    [zoom]="zoom"
    [center]="center"
    (mapClick)="click($event);">

    <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

      <map-marker
        #markerElem
        *ngFor="let marker of cluster.unidades"
        [position]="marker.position"
        [label]="marker.label"
        [title]="marker.title"
        [options]="marker.options"
        (mapClick)="openInfo(markerElem);"
      >
      </map-marker>

    </marker-clusterer-plus>

    <map-info-window>Teste</map-info-window>

  </google-map>

,   styles: [
`
]
})
export class AppComponent implements OnInit, OnChanges {
@ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;
@ViewChild('googleMapRef')
googleMaps : GoogleMap;
@ViewChild('marker-clusterer-plus')
markerClusterer : MarkerClustererPlusComponent;
@Input()
zoom:number = 8;
@Input()
center:google.maps.LatLngLiteral;
@Input()
markers: Array = [];
array_clusteres: Array = [];
constructor(private element: ElementRef) { }
ngOnInit(): void {
navigator.geolocation.getCurrentPosition(position => {
  this.center = {
    lat: position.coords.latitude,
    lng: position.coords.longitude,
  }

  this.loadOptions();

  this.loadDataGeoJson();

});

}
ngAfterViewInit(){
console.log('MaineComponent ngAfterViewInit');
}
loadOptions(){
this.googleMaps._googleMap.setOptions({
  styles: [
    {
      'stylers': [{'visibility': 'on'}]
    },
    {
      'featureType': 'landscape',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
    },
    {
      'featureType': 'water',
      'elementType': 'geometry',
      'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
    }
  ]
});

}
loadDataGeoJson(){
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});
this.googleMaps.data.setStyle(styleFeature);

let enableMouseClick = false;
let enableMouseOver = false;
let enableMouseOut = false;
function styleFeature(feature) {

  var id = feature.getProperty('id');
  var name = feature.getProperty('name');
  var description = feature.getProperty('description');
  var state = feature.getProperty('state');
  var fillColor = '#131958';
  var fillOpacity = 0.3;
  var zIndex = 1;
  var clickable = 'true';
  var showRow = true; // determine whether to show this shape or not

  var options_default = {
      strokeColor: '#1e76ae', // #ffffff
      strokeOpacity: 0.8,
      strokeWeight: 1.5,
      fillColor: fillColor,
      fillOpacity: fillOpacity,
      zIndex: zIndex,
      visible: showRow
  };

  if (name != undefined) {

    if (state == 'click' && enableMouseClick) {}

    if (state == 'normal' && enableMouseOut) {
        feature.setProperty('withInfowindowOpen', false);
    }

    if (state == 'hover' && enableMouseOver) {
        options_default.strokeOpacity = 0.8;
        options_default.strokeColor = '#1e76ae';
        options_default.strokeWeight = 6;
        options_default.fillOpacity = 0.1;
        options_default.zIndex = -1;
    }
  }
  return options_default;
}
  this.googleMaps.data.addListener('click', (e)=>{
   // set the hover state so the setStyle function can change the border
   e.feature.setProperty('state', 'click');
   console.log('CLICK REGION', e.feature);
});

this.googleMaps.data.addListener('mouseover', (e)=>{
  e.feature.setProperty('state', 'hover');
  e.feature.getProperty('NAME');
});

this.googleMaps.data.addListener('mouseout', (e)=>{
  e.feature.setProperty('state', 'normal');
});

}
onMcLoaded(markerClusterer:MarkerClusterer){
this.array_clusteres.push(markerClusterer);
this.fitBoundsCluster(markerClusterer);
}
clearMarkerClusteres(){
this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
mc.clearMarkers();
});
}
fitBoundsCluster(markerClusterer:MarkerClusterer){
let bounds = new google.maps.LatLngBounds();

this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
  mc.getMarkers().forEach( (m)=>{
    bounds.extend(m.getPosition());
  })
})

this.googleMaps.fitBounds(bounds);

}
openInfo(markerElem: MapMarker,content?:string){
this.infoWindow.open(markerElem);
}
addMarker() {
const plusLat = ((Math.random() - 0.5) * 10) / 10;
const plusLng = ((Math.random() - 0.5) * 10) / 10;
this.markers.push({
  position: {
    lat: this.center.lat + plusLat,
    lng: this.center.lng + plusLng,
  },
  label: {
    color: 'red',
    text: 'Marker label ' + (this.markers.length + 1),
  },
  title: 'Marker title ' + (this.markers.length + 1),
  options: {
    // animation: google.maps.Animation.BOUNCE
  },
})

}
click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
App Base - Calling MarkerClustererPlus
### App Base

`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';

@Component({
  selector: 'maine',
  template: `

      <google-map #googleMapRef
        height="100vh"
        width="100%"
        [zoom]="zoom"
        [center]="center"
        (mapClick)="click($event);">

        <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

          <map-marker
            #markerElem
            *ngFor="let marker of cluster.unidades"
            [position]="marker.position"
            [label]="marker.label"
            [title]="marker.title"
            [options]="marker.options"
            (mapClick)="openInfo(markerElem);"
          >
          </map-marker>

        </marker-clusterer-plus>

        <map-info-window>Teste</map-info-window>

      </google-map>

  `,
  styles: [
    `
    `
  ]
})
export class AppComponent implements OnInit, OnChanges {

  @ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;

  @ViewChild('googleMapRef')
  googleMaps : GoogleMap;

  @ViewChild('marker-clusterer-plus')
  markerClusterer : MarkerClustererPlusComponent;

  @Input()
  zoom:number = 8;

  @Input()
  center:google.maps.LatLngLiteral;

  @Input()
  markers: Array<any> = [];

  array_clusteres: Array<MarkerClusterer> = [];

  constructor(private element: ElementRef) { }

  ngOnInit(): void {

    navigator.geolocation.getCurrentPosition(position => {
      this.center = {
        lat: position.coords.latitude,
        lng: position.coords.longitude,
      }

      this.loadOptions();

      this.loadDataGeoJson();

    });

  }

  ngAfterViewInit(){
    console.log('MaineComponent ngAfterViewInit');
  }

  loadOptions(){

    this.googleMaps._googleMap.setOptions({
      styles: [
        {
          'stylers': [{'visibility': 'on'}]
        },
        {
          'featureType': 'landscape',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
        },
        {
          'featureType': 'water',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
        }
      ]
    });
  }

  loadDataGeoJson(){
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});

    this.googleMaps.data.setStyle(styleFeature);

    let enableMouseClick = false;
    let enableMouseOver = false;
    let enableMouseOut = false;
    function styleFeature(feature) {

      var id = feature.getProperty('id');
      var name = feature.getProperty('name');
      var description = feature.getProperty('description');
      var state = feature.getProperty('state');
      var fillColor = '#131958';
      var fillOpacity = 0.3;
      var zIndex = 1;
      var clickable = 'true';
      var showRow = true; // determine whether to show this shape or not

      var options_default = {
          strokeColor: '#1e76ae', // #ffffff
          strokeOpacity: 0.8,
          strokeWeight: 1.5,
          fillColor: fillColor,
          fillOpacity: fillOpacity,
          zIndex: zIndex,
          visible: showRow
      };

      if (name != undefined) {

        if (state == 'click' && enableMouseClick) {}

        if (state == 'normal' && enableMouseOut) {
            feature.setProperty('withInfowindowOpen', false);
        }

        if (state == 'hover' && enableMouseOver) {
            options_default.strokeOpacity = 0.8;
            options_default.strokeColor = '#1e76ae';
            options_default.strokeWeight = 6;
            options_default.fillOpacity = 0.1;
            options_default.zIndex = -1;
        }
      }
      return options_default;
    }
      this.googleMaps.data.addListener('click', (e)=>{
       // set the hover state so the setStyle function can change the border
       e.feature.setProperty('state', 'click');
       console.log('CLICK REGION', e.feature);
    });

    this.googleMaps.data.addListener('mouseover', (e)=>{
      e.feature.setProperty('state', 'hover');
      e.feature.getProperty('NAME');
    });

    this.googleMaps.data.addListener('mouseout', (e)=>{
      e.feature.setProperty('state', 'normal');
    });

  }

  onMcLoaded(markerClusterer:MarkerClusterer){
    this.array_clusteres.push(markerClusterer);
    this.fitBoundsCluster(markerClusterer);
  }

  clearMarkerClusteres(){
    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.clearMarkers();
    });
  }

  fitBoundsCluster(markerClusterer:MarkerClusterer){

    let bounds = new google.maps.LatLngBounds();

    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.getMarkers().forEach( (m)=>{
        bounds.extend(m.getPosition());
      })
    })

    this.googleMaps.fitBounds(bounds);
  }

  openInfo(markerElem: MapMarker,content?:string){
    this.infoWindow.open(markerElem);
  }

  addMarker() {
    const plusLat = ((Math.random() - 0.5) * 10) / 10;
    const plusLng = ((Math.random() - 0.5) * 10) / 10;

    this.markers.push({
      position: {
        lat: this.center.lat + plusLat,
        lng: this.center.lng + plusLng,
      },
      label: {
        color: 'red',
        text: 'Marker label ' + (this.markers.length + 1),
      },
      title: 'Marker title ' + (this.markers.length + 1),
      options: {
        // animation: google.maps.Animation.BOUNCE
      },
    })
  }

  click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

MarkerClustererPlus Component Wrapper
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';

@Component({
  selector: 'marker-clusterer-plus',
  template: `<ng-content></ng-content>`,
  styles: [
  ]
})
export class MarkerClustererPlusComponent
{
  mc: MarkerClusterer;

  @Input()
  googleMaps: GoogleMap;

  @ContentChildren("markerElem")
  mapMarkers: QueryList<MapMarker>;

  @Input()
  title: string;

  @Input()
  icon_path: string;

  map: google.maps.Map;
  options: MarkerClustererOptions;
  styles: Array<ClusterIconStyle>;

  @Output()
  onLoaded: EventEmitter<any> = new EventEmitter<any>();

  constructor() {

    this.options = {
      gridSize: 60,
      maxZoom: 20,
      averageCenter: false,
      zoomOnClick: true,
    };

    this.mc = new MarkerClusterer(null,[],this.options);
  }

  ngAfterViewInit(){
    this.init();
  }

  init(){

    this.map = this.googleMaps._googleMap;

    this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
      this.mc.addMarker(mapMarker._marker);
    });
    this.mc.setTitle(this.title || "MarkerCluster");
    this.styles =[
      {
        url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
        height: 52,
        width: 52,
        anchorText: [30,-10],
        textColor: '#fff',
        textSize: 10,
        fontWeight: "bold",
      }
    ];
    this.mc.setStyles(this.styles);
    this.mc.setMap(this.map);
    this.onLoaded.emit(this.mc);
    this.bindEvents();
  }
  bindEvents(){
    this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
      console.log(cluster);
    });
  }
}

@emiliojva
Thank you for your Code.
In the map-marker Element you iterate cluster.unidades. Where does this come from?
Thanks, Arndt

Is there any update on adding this as a feature to google-maps? This would be terrific!
Thanks!!

@emiliojva
Thank you for your Code.
In the map-marker Element you iterate cluster.unidades. Where does this come from?
Thanks, Arndt

I'm sorry for the delay in responding. 'cluster is just a variable that makes reference to an' array 'of 'unidades'(units in Portuguese) that I return from my api

Any news about this feature ?

Is it at least in the nearest future plans?

@angular/google-maps

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
App Base - Calling MarkerClustererPlus
### App Base

`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';

@Component({
  selector: 'maine',
  template: `

      <google-map #googleMapRef
        height="100vh"
        width="100%"
        [zoom]="zoom"
        [center]="center"
        (mapClick)="click($event);">

        <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

          <map-marker
            #markerElem
            *ngFor="let marker of cluster.unidades"
            [position]="marker.position"
            [label]="marker.label"
            [title]="marker.title"
            [options]="marker.options"
            (mapClick)="openInfo(markerElem);"
          >
          </map-marker>

        </marker-clusterer-plus>

        <map-info-window>Teste</map-info-window>

      </google-map>

  `,
  styles: [
    `
    `
  ]
})
export class AppComponent implements OnInit, OnChanges {

  @ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;

  @ViewChild('googleMapRef')
  googleMaps : GoogleMap;

  @ViewChild('marker-clusterer-plus')
  markerClusterer : MarkerClustererPlusComponent;

  @Input()
  zoom:number = 8;

  @Input()
  center:google.maps.LatLngLiteral;

  @Input()
  markers: Array<any> = [];

  array_clusteres: Array<MarkerClusterer> = [];

  constructor(private element: ElementRef) { }

  ngOnInit(): void {

    navigator.geolocation.getCurrentPosition(position => {
      this.center = {
        lat: position.coords.latitude,
        lng: position.coords.longitude,
      }

      this.loadOptions();

      this.loadDataGeoJson();

    });

  }

  ngAfterViewInit(){
    console.log('MaineComponent ngAfterViewInit');
  }

  loadOptions(){

    this.googleMaps._googleMap.setOptions({
      styles: [
        {
          'stylers': [{'visibility': 'on'}]
        },
        {
          'featureType': 'landscape',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
        },
        {
          'featureType': 'water',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
        }
      ]
    });
  }

  loadDataGeoJson(){
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});

    this.googleMaps.data.setStyle(styleFeature);

    let enableMouseClick = false;
    let enableMouseOver = false;
    let enableMouseOut = false;
    function styleFeature(feature) {

      var id = feature.getProperty('id');
      var name = feature.getProperty('name');
      var description = feature.getProperty('description');
      var state = feature.getProperty('state');
      var fillColor = '#131958';
      var fillOpacity = 0.3;
      var zIndex = 1;
      var clickable = 'true';
      var showRow = true; // determine whether to show this shape or not

      var options_default = {
          strokeColor: '#1e76ae', // #ffffff
          strokeOpacity: 0.8,
          strokeWeight: 1.5,
          fillColor: fillColor,
          fillOpacity: fillOpacity,
          zIndex: zIndex,
          visible: showRow
      };

      if (name != undefined) {

        if (state == 'click' && enableMouseClick) {}

        if (state == 'normal' && enableMouseOut) {
            feature.setProperty('withInfowindowOpen', false);
        }

        if (state == 'hover' && enableMouseOver) {
            options_default.strokeOpacity = 0.8;
            options_default.strokeColor = '#1e76ae';
            options_default.strokeWeight = 6;
            options_default.fillOpacity = 0.1;
            options_default.zIndex = -1;
        }
      }
      return options_default;
    }
      this.googleMaps.data.addListener('click', (e)=>{
       // set the hover state so the setStyle function can change the border
       e.feature.setProperty('state', 'click');
       console.log('CLICK REGION', e.feature);
    });

    this.googleMaps.data.addListener('mouseover', (e)=>{
      e.feature.setProperty('state', 'hover');
      e.feature.getProperty('NAME');
    });

    this.googleMaps.data.addListener('mouseout', (e)=>{
      e.feature.setProperty('state', 'normal');
    });

  }

  onMcLoaded(markerClusterer:MarkerClusterer){
    this.array_clusteres.push(markerClusterer);
    this.fitBoundsCluster(markerClusterer);
  }

  clearMarkerClusteres(){
    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.clearMarkers();
    });
  }

  fitBoundsCluster(markerClusterer:MarkerClusterer){

    let bounds = new google.maps.LatLngBounds();

    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.getMarkers().forEach( (m)=>{
        bounds.extend(m.getPosition());
      })
    })

    this.googleMaps.fitBounds(bounds);
  }

  openInfo(markerElem: MapMarker,content?:string){
    this.infoWindow.open(markerElem);
  }

  addMarker() {
    const plusLat = ((Math.random() - 0.5) * 10) / 10;
    const plusLng = ((Math.random() - 0.5) * 10) / 10;

    this.markers.push({
      position: {
        lat: this.center.lat + plusLat,
        lng: this.center.lng + plusLng,
      },
      label: {
        color: 'red',
        text: 'Marker label ' + (this.markers.length + 1),
      },
      title: 'Marker title ' + (this.markers.length + 1),
      options: {
        // animation: google.maps.Animation.BOUNCE
      },
    })
  }

  click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

MarkerClustererPlus Component Wrapper
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';

@Component({
  selector: 'marker-clusterer-plus',
  template: `<ng-content></ng-content>`,
  styles: [
  ]
})
export class MarkerClustererPlusComponent
{
  mc: MarkerClusterer;

  @Input()
  googleMaps: GoogleMap;

  @ContentChildren("markerElem")
  mapMarkers: QueryList<MapMarker>;

  @Input()
  title: string;

  @Input()
  icon_path: string;

  map: google.maps.Map;
  options: MarkerClustererOptions;
  styles: Array<ClusterIconStyle>;

  @Output()
  onLoaded: EventEmitter<any> = new EventEmitter<any>();

  constructor() {

    this.options = {
      gridSize: 60,
      maxZoom: 20,
      averageCenter: false,
      zoomOnClick: true,
    };

    this.mc = new MarkerClusterer(null,[],this.options);
  }

  ngAfterViewInit(){
    this.init();
  }

  init(){

    this.map = this.googleMaps._googleMap;

    this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
      this.mc.addMarker(mapMarker._marker);
    });
    this.mc.setTitle(this.title || "MarkerCluster");
    this.styles =[
      {
        url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
        height: 52,
        width: 52,
        anchorText: [30,-10],
        textColor: '#fff',
        textSize: 10,
        fontWeight: "bold",
      }
    ];
    this.mc.setStyles(this.styles);
    this.mc.setMap(this.map);
    this.onLoaded.emit(this.mc);
    this.bindEvents();
  }
  bindEvents(){
    this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
      console.log(cluster);
    });
  }
}

Is this working with latest angular version ? I see there are lot of issues such as

Hi guys!
I built my own Component normally. Although I have to inject the inputs and outputs at the base of the application.
App Base - Calling MarkerClustererPlus
### App Base

`
import { Component, OnInit, ViewChild, Input, OnChanges, SimpleChanges, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';
import { MapMarker, MapInfoWindow, GoogleMap } from '@angular/google-maps';
import { MarkerClustererPlusComponent } from '../marker-clusterer-plus/marker-clusterer-plus.component';
import MarkerClusterer from '@google/markerclustererplus';

@Component({
  selector: 'maine',
  template: `

      <google-map #googleMapRef
        height="100vh"
        width="100%"
        [zoom]="zoom"
        [center]="center"
        (mapClick)="click($event);">

        <marker-clusterer-plus [googleMaps]="googleMapRef" (onLoaded)="onMcLoaded($event)" *ngFor="let cluster of markers" [icon_path]="cluster.instituicao.icon_path">

          <map-marker
            #markerElem
            *ngFor="let marker of cluster.unidades"
            [position]="marker.position"
            [label]="marker.label"
            [title]="marker.title"
            [options]="marker.options"
            (mapClick)="openInfo(markerElem);"
          >
          </map-marker>

        </marker-clusterer-plus>

        <map-info-window>Teste</map-info-window>

      </google-map>

  `,
  styles: [
    `
    `
  ]
})
export class AppComponent implements OnInit, OnChanges {

  @ViewChild(MapInfoWindow,{static:false}) infoWindow: MapInfoWindow;

  @ViewChild('googleMapRef')
  googleMaps : GoogleMap;

  @ViewChild('marker-clusterer-plus')
  markerClusterer : MarkerClustererPlusComponent;

  @Input()
  zoom:number = 8;

  @Input()
  center:google.maps.LatLngLiteral;

  @Input()
  markers: Array<any> = [];

  array_clusteres: Array<MarkerClusterer> = [];

  constructor(private element: ElementRef) { }

  ngOnInit(): void {

    navigator.geolocation.getCurrentPosition(position => {
      this.center = {
        lat: position.coords.latitude,
        lng: position.coords.longitude,
      }

      this.loadOptions();

      this.loadDataGeoJson();

    });

  }

  ngAfterViewInit(){
    console.log('MaineComponent ngAfterViewInit');
  }

  loadOptions(){

    this.googleMaps._googleMap.setOptions({
      styles: [
        {
          'stylers': [{'visibility': 'on'}]
        },
        {
          'featureType': 'landscape',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
        },
        {
          'featureType': 'water',
          'elementType': 'geometry',
          'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
        }
      ]
    });
  }

  loadDataGeoJson(){
this.googleMaps.data.loadGeoJson('https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/rio-de-janeiro.geojson', {idPropertyName: 'STATE'});

    this.googleMaps.data.setStyle(styleFeature);

    let enableMouseClick = false;
    let enableMouseOver = false;
    let enableMouseOut = false;
    function styleFeature(feature) {

      var id = feature.getProperty('id');
      var name = feature.getProperty('name');
      var description = feature.getProperty('description');
      var state = feature.getProperty('state');
      var fillColor = '#131958';
      var fillOpacity = 0.3;
      var zIndex = 1;
      var clickable = 'true';
      var showRow = true; // determine whether to show this shape or not

      var options_default = {
          strokeColor: '#1e76ae', // #ffffff
          strokeOpacity: 0.8,
          strokeWeight: 1.5,
          fillColor: fillColor,
          fillOpacity: fillOpacity,
          zIndex: zIndex,
          visible: showRow
      };

      if (name != undefined) {

        if (state == 'click' && enableMouseClick) {}

        if (state == 'normal' && enableMouseOut) {
            feature.setProperty('withInfowindowOpen', false);
        }

        if (state == 'hover' && enableMouseOver) {
            options_default.strokeOpacity = 0.8;
            options_default.strokeColor = '#1e76ae';
            options_default.strokeWeight = 6;
            options_default.fillOpacity = 0.1;
            options_default.zIndex = -1;
        }
      }
      return options_default;
    }
      this.googleMaps.data.addListener('click', (e)=>{
       // set the hover state so the setStyle function can change the border
       e.feature.setProperty('state', 'click');
       console.log('CLICK REGION', e.feature);
    });

    this.googleMaps.data.addListener('mouseover', (e)=>{
      e.feature.setProperty('state', 'hover');
      e.feature.getProperty('NAME');
    });

    this.googleMaps.data.addListener('mouseout', (e)=>{
      e.feature.setProperty('state', 'normal');
    });

  }

  onMcLoaded(markerClusterer:MarkerClusterer){
    this.array_clusteres.push(markerClusterer);
    this.fitBoundsCluster(markerClusterer);
  }

  clearMarkerClusteres(){
    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.clearMarkers();
    });
  }

  fitBoundsCluster(markerClusterer:MarkerClusterer){

    let bounds = new google.maps.LatLngBounds();

    this.array_clusteres.forEach( (mc:MarkerClusterer)=>{
      mc.getMarkers().forEach( (m)=>{
        bounds.extend(m.getPosition());
      })
    })

    this.googleMaps.fitBounds(bounds);
  }

  openInfo(markerElem: MapMarker,content?:string){
    this.infoWindow.open(markerElem);
  }

  addMarker() {
    const plusLat = ((Math.random() - 0.5) * 10) / 10;
    const plusLng = ((Math.random() - 0.5) * 10) / 10;

    this.markers.push({
      position: {
        lat: this.center.lat + plusLat,
        lng: this.center.lng + plusLng,
      },
      label: {
        color: 'red',
        text: 'Marker label ' + (this.markers.length + 1),
      },
      title: 'Marker title ' + (this.markers.length + 1),
      options: {
        // animation: google.maps.Animation.BOUNCE
      },
    })
  }

  click(e: google.maps.MouseEvent) { console.log( JSON.stringify( e.latLng.toJSON() ) ); }
}
`

MarkerClustererPlus Component Wrapper
import { Component, Input, ContentChildren, QueryList, EventEmitter, Output } from '@angular/core';
import { GoogleMap, MapMarker } from '@angular/google-maps';
import MarkerClusterer, {ClusterIconStyle,MarkerClustererOptions} from '@google/markerclustererplus';
import { Cluster } from '@google/markerclustererplus/dist/cluster';

@Component({
  selector: 'marker-clusterer-plus',
  template: `<ng-content></ng-content>`,
  styles: [
  ]
})
export class MarkerClustererPlusComponent
{
  mc: MarkerClusterer;

  @Input()
  googleMaps: GoogleMap;

  @ContentChildren("markerElem")
  mapMarkers: QueryList<MapMarker>;

  @Input()
  title: string;

  @Input()
  icon_path: string;

  map: google.maps.Map;
  options: MarkerClustererOptions;
  styles: Array<ClusterIconStyle>;

  @Output()
  onLoaded: EventEmitter<any> = new EventEmitter<any>();

  constructor() {

    this.options = {
      gridSize: 60,
      maxZoom: 20,
      averageCenter: false,
      zoomOnClick: true,
    };

    this.mc = new MarkerClusterer(null,[],this.options);
  }

  ngAfterViewInit(){
    this.init();
  }

  init(){

    this.map = this.googleMaps._googleMap;

    this.mapMarkers.forEach( (mapMarker:MapMarker)=>{
      this.mc.addMarker(mapMarker._marker);
    });
    this.mc.setTitle(this.title || "MarkerCluster");
    this.styles =[
      {
        url: this.icon_path || "http://image.flaticon.com/icons/svg/252/252025.svg",
        height: 52,
        width: 52,
        anchorText: [30,-10],
        textColor: '#fff',
        textSize: 10,
        fontWeight: "bold",
      }
    ];
    this.mc.setStyles(this.styles);
    this.mc.setMap(this.map);
    this.onLoaded.emit(this.mc);
    this.bindEvents();
  }
  bindEvents(){
    this.mc.addListener( 'mouseover' , (cluster:Cluster)=>{
      console.log(cluster);
    });
  }
}

@emiliojva  I just tried the same code in latest angular and am getting errors and map is not getting loaded.
Could you please help me ?

@pvkrijesh  What is your errors ? can you create a stackblitz or something like that ?

@pvkrijesh What is your errors ? can you create a stackblitz or something like that ?

@ybarbaria  I have created a stackblitz and please check it below.
https://stackblitz.com/edit/angular-9-google-maps-hpfnlu?file=src%2Fapp%2Fapp.component.ts.
I am expecting some clusters and on click of it should show the pins.
Hope this will help you to figure it out whats wrong.

@pvkrijesh
So in your app.component you have this array array_clusteres and this one markers but your never instantiate them or even add some data, your clusters won't be draw without data...

Hi @emiliojva,
Thank you for your code ! I tried to implemented it in my project, but I can't have what I want.
For now I'm only able to have the markers displayed, not the clusters...
I'm still not understanding the interest of the array_clusteres in your code as I can't see where it's used.
Do you have a working example with just few initial data ?

https://github.com/angular/components/pull/20944

authors: Ajax-ua Akxe Arni82 GeoffreyEhrmann Tsar09 anna0312 emiliojva mbehrlich pvkrijesh runette salorium ybarbaria

repo: angular/components


text:
bug(mat-select): has different height than matInput

Is this a regression?

[ ] Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was
13.2.3
Description
If you render a mat-input and a mat-select component next to each other you can see that mat-select is slightly higher than the mat-input. This is a specific appearance="outline" issue. Using appearance="fill" the height is the exact same. (see https://material.angular.io/components/form-field/examples)
Mat Input
mat-form-field

.mat-form-field-infix

Mat Select
mat-form-field

.mat-form-field-infix

Reproduction
StackBlitz Demo
Expected Behavior
All form components should have the same height.
Actual Behavior
The height is different when using appearance="outline"
Environment

Angular: 13.0.x
CDK/Material: 13.2.3
Browser(s): Chrome 98.0.4758.102
Operating System Windows

Anything new on this? I have a similar problem, but for me mat-input is taller with appearance='fiill'

source: gharchive/issue

authors: kroeder lordofdestiny

license: MIT

license_type: permissive

license_source: github-api


text:
bug(Chips Autocomplete): Autocomplete panel doesn't close when a chip gets canceled.

Is this a regression?

[ ] Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was
No response
Description
This happens to the chips with auto complete control. If the panel is open with 2 rows of chips, the autocomplete panel doesn't come up when chips are canceled and the input box jumps back to 1 row, leaving a gap between the open panel and the input control.
This happens to the example on the material angular website:
https://material.angular.io/components/chips/overview#autocomplete
Reproduction
Steps to reproduce:

Add chips until 2 rows are occupied in.
Open the autocomplete panel
Cancel chips
Result: Control jumps back to 1 row, the panel stays where it is leaving a gap between the panel and the control.

Expected Behavior
Expected result:
option1: Panel sticks to the control
option2: Panel closes when canceling chips.
Actual Behavior
Control jumps back to 1 row, the panel stays where it is leaving a gap between the panel and the control.
Chips with 2 rows:

Chips after chips have been canceled with the autocomplete panel left open:

It happens to previous versions as well.
Environment

Angular:
This happens to the example on the material angular website:
https://material.angular.io/components/chips/overview#autocomplete
Seen in versions 15,14,13,12
CDK/Material:
Browser(s):
Chrome
Operating System (e.g. Windows, macOS, Ubuntu):
Windows

Solved it by adding MatAutocompleteTrigger as view child and closing the panel manually.
html:
<button matChipRemove [attr.aria-label]="'remove ' + chip. Value" (click)="_closeAutoCompletePanel()_">             <mat-icon>cancel</mat-icon>
TS:
@ViewChild(MatAutocompleteTrigger) autocomplete?: MatAutocompleteTrigger;
...
public closeAutoCompletePanel()   {     if (this. Autocomplete) {       this.autocomplete.closePanel();     }   }


text:
Proposal: remove background-color from .mat-drawer-container

Bug, feature request, or proposal:
Proposal: remove background-color from .mat-drawer-container
What is the expected behavior?
The common background that I've set in my app appears on a page with a drawer
What is the current behavior?
Putting a drawer on a page requires putting the page contents inside md-drawer-container which comes with background-color set that overrides any app background that's been set.
What are the steps to reproduce?
Add a drawer to a page with a non-standard background
What is the use-case or motivation for changing an existing behavior?
Overlays for drawers and sliders are typically supposed to block the majority of the UI. IMHO material shouldn't be providing a background-color for this majority.
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
2.0.0-beta.10
Is there anything else we should know?

I agree with @adamdport I have to override this background color every time.

You might as well add .color to that as well as it overrides both

PLease do it.

thats what is there currently , why ?
background-color: #fafafa;
color: rgba(0,0,0,.87);

This mat-drawer css is broken. It even overwrites my "routerLinkActive" color.

A fix would be really appreciated. You cant offer theming and say that the components support it and then you have to set the background color of some components manually

I asked this question on stackoverflow, maybe it can help..
<mat-drawer-container class="red-container">
...
</mat-drawer-container>

.red-container {
  background-color: red;
}

These seems like a trivial fix. Has there been any movement on this?

This can cause very slight visual regressions in existing projects where background colors are just #FFF white, and makes it so that a first experience of implementing an Angular Material component requires a style FIX, as opposed to a style customization. Which in turn does not provide a good first experience, which is a bummer. Why is it there?

This is still open right? Not the first time I end up in this issue. I would like to also suggest to add the possibility of setting the color of the drawer using the app theme e.j. (color="primary")

authors: DjStorm HuiiBuh RamZal365 adamdport ja5onkendall michahell paco76 rickdgray rtaft upondeep wintersommer


text:
fix(cdk/drag-drop): resolve helper directives with DI for proper hostDirectives support

Currently CdkDrag resolves its helper directives (e.g. handle or preview) using a content query, but that doesn't work when it's applied as a host directive, because no content is being projected.
These changes switch to having the helper directives inject the closest drag directive and register themselves manually.
Fixes #28614.

@crisbeto our app uses some nested drag-drop and this PR has broken the functionality. It seems that the cdkDragHandle is connecting to the wrong cdkDrag. I have not diagnosed exactly the issue yet but will get back to you.

I think the changes in this commit may have caused a dependency injection issue when combining virtual scroll and drag and drop. I've setup a very minimal StackBlitz example to show the issue here: https://stackblitz.com/edit/f2xpkk. If you load the example as it is currently with version 17.2.2, you'll see the following stack trace:
vendor.js:47027 ERROR NullInjectorError: R3InjectorError(Standalone[CdkVirtualScrollAppendOnlyExample])[InjectionToken CDK_DRAG_PARENT -> InjectionToken CDK_DRAG_PARENT -> InjectionToken CDK_DRAG_PARENT]:    NullInjectorError: No provider for InjectionToken CDK_DRAG_PARENT!     at NullInjector.get (vendor.js:44290:21)     at R3Injector.get (vendor.js:44741:27)     at R3Injector.get (vendor.js:44741:27)     at R3Injector.get (vendor.js:44741:27)     at ChainedInjector.get (vendor.js:55693:32)     at lookupTokenUsingModuleInjector (vendor.js:46282:31)     at getOrCreateInjectable (vendor.js:46328:10)     at ɵɵdirectiveInject (vendor.js:49755:17)     at ɵɵinject (vendor.js:43467:59)     at inject (vendor.js:43550:10)
If you go to package.json and set all the angular packages to 17.2.1 and refresh, the page will load with no issues. Is this expected or intentional based on the layout of the component?

source: gharchive/pull-request

authors: crisbeto joergbaier sdoyle0


text:
[MatSelect] Order in multiple mode

Bug, feature request, or proposal:
feature
What is the expected behavior?
Using MatSelect with multiple selection,(selectionChange) will give the result which sort by user selected order.
What is the current behavior?
When using MatSelect with multiple selection,(selectionChange) will give the result which sort by selected options order.I think this order should defined by developer,such as sort by user select or default options order.
What are the steps to reproduce?
Providing a StackBlitz reproduction is the best way to share your issue.
StackBlitz starter: https://goo.gl/wwnhMV
What is the use-case or motivation for changing an existing behavior?
Make select value sort rules defined by developer.
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Angular: 6.0.0,
Material: 6.0.1,
OS: win10,
TypeScript: 2.7.2,
Browsers: Chrome@67.0.3396.87
Is there anything else we should know?

You should be able to sort the values yourself when you get it in the selection change event.

@crisbeto Yes, I have fixed by this way.But in <mat-selcect #select></mat-select> , It's only way to overwrite the text by select._elementRef.nativeElement.firstChild.firstChild.children[0].innerText = 'b,a,c'. In fact, I'm already finish this case,just give some advice for better component.

authors: crisbeto yooRabbit


text:
MdMenu: Items with MdIcons appear on two lines in FireFox

Bug, feature request, or proposal:
If you have an MdMenu where the menu items are an MdIcon and text, the items will split into two lines on Firefox (contrary to the README for MdMenu).
What is the expected behavior?
A single line as shown in the MdMenu README
What is the current behavior?
Two lines are created for the MenuItem
What are the steps to reproduce?
This Plunker uses the exact HTML has the example for MdMenu, open it in FireFox and click the menu trigger button at the bottom
http://plnkr.co/edit/KvR8H9ZReNHzwcnFIj6H?p=preview
What is the use-case or motivation for changing an existing behavior?
It doesn't look as expected
Which versions of Angular, Material, OS, browsers are affected?
Latest, Latest, Ubuntu, FireFox
Is there anything else we should know?

Firefox doesn't support display: flex in a button.
Just put a div inside of your <button>, and make that div display:flex.
This should temporarily solve your problem for Firefox.
http://stackoverflow.com/questions/24289251/flexbox-not-working-in-buttons-in-firefox

Can this be closed?
Copied repro to latest template: http://plnkr.co/edit/IC0zXmiPr4UcvBAAajT8?p=preview
FF 45.0

FF 53.0

authors: dahaupt jermowery willshowell


text:
Input hints can only contain single-line text

Bug, feature request, or proposal:
Bug/Feat/Proposal
What is the expected behavior?
As you can see in Angular Material 1, I would expect the hint text to stay below the input field even when it contains more than one line of text .
What is the current behavior?
md-hint element's content is overlapping the corresponding input field if the hint contains multi-line text, due to the CSS rules that are applied to md-hint elements by default. I.E. position:absolute and bottom: 0
What are the steps to reproduce?
Just add a multi-line text into a md-hint.

What is the use-case or motivation for changing an existing behavior?
It'd be useful to have multi-line hints under some input field to point out several warnings in a form at the same time.
Which versions of Angular, Material, OS, browsers are affected?
Angular 2.4.8
Material 2.0.0-beta.2
on latest versions of Chrome and Firefox
Is there anything else we should know?
Maybe you should reconsider the absolute positioning of the md-hint element to solve this issue.

+1

+1

+1

@mmalerba the issue has been fix?

+1

+1

@finalxcode This one is still in discussion but I'm sure we will see this getting fixed within the next weeks after ng-conf. The conference is most likely the reason why the team is currently not that active here on the repo.

@dahaupt thanks

authors: JosuaMeier anapanadero dahaupt finalxcode ianhatton iliketomatoes jefersonestevo


text:
Input component coloring not consistent with material design spec

Bug, feature request, or proposal:
Bug
What is the expected behavior?
color of input element on focus is ACCENT color
What is the current behavior?
color of input element on focus is PRIMARY color
What are the steps to reproduce?
Put focus to input field on demo page
https://material.angular.io/components/component/input
What is the use-case or motivation for changing an existing behavior?
Match existing Material Design Spec (https://material.io/guidelines/style/color.html#color-color-schemes)
Which versions of Angular, Material, OS, browsers are affected?
current Material build - 2.0.0-beta.2 (and angular material demo page)

The text field spec shows primary color in all the examples. You can change the color in your app by using the color property on the input container.

authors: jelbourn mhengelein


text:
install error even with latest npm

Bug
getting the below error for npm install of material core.
Which versions of Angular, Material, OS, browsers are affected?
node version  4.4.5
npm version 3.9.3
What is the current behavior?

@angular2-material

aahh... my bad.. very sorry...

authors: balasivagnanam msegers


text:
Input and select placeholders are not correctly placed

Bug, feature request, or proposal:
bug
What is the expected behavior?
https://material.angular.io/components/input/overview
https://material.angular.io/components/select/overview
What is the current behavior?
Select placeholder has a lot of empty space :
Input placeholder is missplaced:
What are the steps to reproduce?
Just create a mat-form-field with an input / a select inside, I followed the documentation exemples
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Angular CLI : 1.4.7
Angular core : 4.4.4
Angular material : 2.0.0-beta.12
OS : Windows 10 x64 / MacOs 10.13
Is there anything else we should know?
Tested on Chrome 61, I don't have this issue with the beta.8

Which browser did you find this? Looks good for me on Opera 48.0.2685.39, Chrome 61, and Firefox 56 on Pop_OS (built on Ubuntu) 17.10

Oops, forgot that information. I tested it on Chrome 61

Same issue with mat-select, I see a lot of empty space
<mat-form-field>
   <mat-select matInput
		placeholder="{{'pass.new.labels.enginetype' | translate }}"
		formControlName="engineType"> <mat-option
		*ngFor="let engineType of engineTypes" [value]="engineType.value">
		{{ engineType.value }} </mat-option> </mat-select>
 </mat-form-field>

@Kornhe you're seeing it on the docs site in Chrome 61? Or you're seeing it in your own application? Can you provide a reproduction?
@lippomano do you have any old workarounds that add custom styles to your mat-select? A lot of folks added some css workarounds to keep them consistent until they were aligned natively, which is now the case in beta.12.

@willshowell No, I'm seeing it on my own application, sorry for the confusion. Here is the code :
  <mat-form-field color="accent">
    <mat-select formControlName="countMethod" placeholder="Mode de décompte">
      <mat-option *ngFor="let method of countMethods" [value]="method.value">{{ method.displayValue }}</mat-option>
    </mat-select>
  </mat-form-field>

This is included in a  MatDialog, however, putting it outside does not fix the issue

@Kornhe Are you positive you don't have any overriding css? As I mentioned in my last comment, lots of people added a workaround to align the input and select before it was handled natively. You may have forgotten about some global css you dropped in a while back.
If you're sure, then I don't think there's much the team will be able to do without a reproduction.

@willshowell I'm 100% sure I don't have any css overriding it, I removed all my stylesheets but it gives me the same results.
The select is part of a <form> ... </form>, I don't know if this is an issue but I don't think

I have the same issue.

Can someone experiencing these issues please create a plunker or stackblitz demonstrating it?

I had the same issue, and as @willshowell stated, there was still an old
mat-select {    margin-top: 30px; }
Deleting my old workaround-line fixed it.

@mmalerba : For the mat-select, @willshowell was right, I had a margin-top leaking on it, causing the spacing. However, the input placeholder is not affected by any css, I double checked for that.

@Kornhe are you using angular 4.4.4 or higher? it contains a fix for a whitespace bug that affected the select placeholder

@mmalerba Yup, but has I said, I fixed the select placeholder, however, I can't find a fix for the input placeholder. This issue appeared when I made the transition to Angular 4.4.4 and Angular Material beta 12

In short, when you perform a transform on the mat-select, the placeholder doesn't stay attached to the box...

authors: Kornhe MoxxNull anvial baruchvlz fiferjanis lippomano mmalerba willshowell


text:
Mat-dialog component does not use selector in DOM, causes "The selector [...] does not match any elements" error

Bug, feature request, or proposal:
In the stackblitz for mat-dialog, the dialog-content-example-dialog component does not use the selector <dialog-content-example-dialog> and causes "Error: The selector "dialog-content-example-dialog" did not match any elements at...". Following the example in my own project causes the same error.
When I add the selector to the html, it causes "Unhandled Promise rejection: StaticInjectorError[MatDialogRef]: StaticInjectorError[MatDialogRef]: NullInjectorError: No provider for MatDialogRef!
What is the expected behavior?
No errors when using mat-dialog as described in the stackblitz.
What is the current behavior?
Errors when following the example.
What are the steps to reproduce?
Just open the stackblitz and look at the console.
https://stackblitz.com/angular/dgjvllndexp?file=app%2Fdialog-content-example.html
What is the use-case or motivation for changing an existing behavior?
Avoiding errors
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
I'm using Angular 5.0.1, Material 5.0.0-rc0, Typescript 2.4.2, latest version of Chrome (Version 62.0.3202.94)
Is there anything else we should know?
I'm still learning Angular 2+ and Material2 so I may just be missing something obvious.

I'm facing the exact same issue.
In order to get the dialog to work it has to be put in the bootstrap section, in the app module declaration. I'm guessing that, since the dialog selector is not explicitly written anywhere, then the error.

Found a fix for this in this issue. I tried the solution and it worked for me.

Fixed here - https://github.com/angular/material.angular.io/pull/356

Looks like this has been fixed.

authors: amcdnl crisbeto richardstangl rodschulz


text:
How to validate if element is non-editable.

Hi All,
I have a strange case to validate if a particular element is non-editable.
Unfortunately, this is a label element and hence it is non-editable.
So .isEnabled() always returns true and my test case is failing.
How to handle this situation to see if this element is non-editable.

Hi there!
Your question is better suited for StackOverflow or Gitter. Please ask a question there with the 'protractor' tag or post in the Gitter Channel to get help.
From the the getting help section of the README:

Please ask usage and debugging questions on StackOverflow (use the "protractor" tag) or in the Angular discussion group. (Please do not ask support questions here on Github.)

Thanks!

authors: NickTomlin deemash

repo: angular/protractor


text:
getCssValue() doesn't work as listed in the doc

Hello,
I'm trying to get the CSS value without success by following the documentation for http://www.protractortest.org/#/api?view=webdriver.WebElement.prototype.getCssValue
it('test using getCssValue()', function(done) {
        var inputField = element(by.css("#searchBoxNew"));
        expect(inputField.getCssValue().indexOf("rgb(105, 105, 105)")).to.eventually.not.equal(-1).notify(done);
    });

result >>>> TypeError: inputField.getCssValue(...).indexOf is not a function
Am I not doing exactly the same as the example in the doc? I am not doing this on an angular page but a normal web page. Does that make any difference?
In comparison, here is what I have to go through to get the CSS:
it('test using computedStyle()', function(done) {
        var inputField = element(by.css("#searchBoxNew"));
        browser.executeScript(function (el) {
            return window.getComputedStyle(el).getPropertyValue('color');
        }, inputField.getWebElement()).then(function (color) {
            expect(color).to.equal("rgb(105, 105, 105)");
            done();
        });
    });

I'm attaching a screenshot of my CSS.

Hi @Francoyy
I think this is related to 4246. There is a wrong example in the docs, that needs to be fixed. A correct working example is in the issue.
Got fixing it on my list, but a new website will only be build with a new release.
As it is related to an other issue that needs to be solved I'm gonna close this one for now.

Thanks a lot!

authors: Francoyy wswebcreation


text:
Implement trajectory splitting by observation gaps

If the time difference between successive records exceeds the provided limit, the trajectory should be split

repo: anitagraser/movingpandas


text:
Gogoanime domain after change a name domain name old or new episode are not downloading in aniyomi library app

Source information
Gogoanime 13.78
Source language
English
Steps to reproduce
Ok
Expected behavior
Episode are not downloading gogoanime domain after change a name
Actual behavior
Some one help
Aniyomi version
0.12.13.10
Android version
Android 11
Other details
Please help
Acknowledgements

[X] I have searched the existing issues and this is a new ticket, NOT a duplicate or related to another open or closed issue.
[X] I have written a short but informative title.
[X] I have updated the app to version 0.12.3.10.
[X] I have updated all installed extensions.
[X] I have tried the troubleshooting guide.
[X] If this is an issue with the app itself, I should be opening an issue in the app repository.
[X] I will fill out all of the requested information in this form.

Are you able to watch the episodes?

Are you able to watch the episodes?

Yes I am able watch episode
But I am not able download old episode or new episode this is issue 😞😞 gogoanime domain I am recently update Gogoanime domain

If you're able to watch the episodes, then the extension is working just fine. Any downloading problems would be the app's fault.

repo: aniyomiorg/aniyomi-extensions


text:
Error 404 in AnimesVision extension (Pt br)

Source information
AnimesVision (Brasil) 14.23
Source language
Português (Brasil)
Steps to reproduce
404 error warning when performing any search in the extension.
Expected behavior
The research should have results.
Actual behavior
Message appearance: "HTTP 404, Check the website in webview.
Aniyomi version
r7493
Android version
Android 11
Other details

Acknowledgements

[X] I have searched the existing issues and this is a new ticket, NOT a duplicate or related to another open or closed issue.
[X] I have written a short but informative title.
[X] I have updated the app to version 0.12.3.10.
[X] I have updated all installed extensions.
[X] I have tried the troubleshooting guide.
[X] If this is an issue with the app itself, I should be opening an issue in the app repository.
[X] I will fill out all of the requested information in this form.

Problem solved, thank you very much
Em qua., 14 de fev. de 2024 18:57, jmir1 @.***>
escreveu:

Closed #2924
https://github.com/aniyomiorg/aniyomi-extensions/issues/2924 as
completed via #2932
https://github.com/aniyomiorg/aniyomi-extensions/pull/2932.
—
Reply to this email directly, view it on GitHub
https://github.com/aniyomiorg/aniyomi-extensions/issues/2924#event-11807445201,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/A3NYHGGMDQB2BAC2IKREC63YTUXNTAVCNFSM6AAAAABDGUWSBCVHI2DSMVQWIX3LMV45UABCJFZXG5LFIV3GK3TUJZXXI2LGNFRWC5DJN5XDWMJRHAYDONBUGUZDAMI
.
You are receiving this because you authored the thread.Message ID:
@.***
com>


text:
Most extensions problem

I have all latest version of aniyomi and extension
When I play any anime by 9Anime it shows like this
https://user-images.githubusercontent.com/109021433/182745606-f78c7228-1799-4dc7-82b5-7770c1b34731.mp4
https://user-images.githubusercontent.com/109021433/182745739-8991c000-50fc-485c-9c0b-b7f3cc3de611.mp4
Please help out

Same

If this is an issue with an extension, I should be opening an issue in the extensions repository.

To add/fix extensions, make a github issue here if it does not exist already
https://github.com/aniyomiorg/aniyomi-extensions

repo: aniyomiorg/aniyomi


text:
screenshot link dead

hi,
just for inform u your screenshot link is dead on your first page ;)
https://camo.githubusercontent.com/2e0e5450faeac0d6eca09a0bdd852e0d36f8136e/68747470733a2f2f70676865726f2e6865726f6b756170702e636f6d2f6173736574732f636f6e736f6c652d37356539396334613665303439393433646136656261363662336437353865372e706e67
bye

Hey @jyriok, thanks for reporting 👍  Somehow missed this. Fixed now.

authors: ankane jyriok

license: mit

license_source: bigquery


text:
Replace UNSAFE_componentWillReceiveProps with getDerivedStateFromProps

Based on https://github.com/ankeetmaini/react-infinite-scroll-component/pull/178

even after making these changes, chrome still gives me the same error about UNSAFE_componentWillReceiveProps.  very odd.

Anybody home?

Sorry for the really long delay. I was too busy. I have updated the PR so that the loader will hide after the component updates. I'm not sure why I have deleted these lines in the first place. Good catch @ankeetmaini :)

Who can merge it?

I'll do a release later today! Thanks :)

authors: Newbie012 ankeetmaini iblokhin jasonchilcott


text:
Hides when body is hidden

I was trying to change a website, and to make the body hidden using display: none. Of course, the stylebot editor is part of the body, so it dissapeared. In the end I had to get it back with inspect element, and turn live preview off so I could finish editing. Could there be some kind of automatic override so that it would hide everything except the editor?

@Booligoosh - can you wrap everything inside  into a different container, and then hide that container instead of hiding the ?

@raajtram but stylebot can only edit css, right?

@Booligoosh - ah, my bad - I thought you were working on your own website. Nevertheless, unless that website is poorly built, you can hide the few main containers on that site to effectively hide everything.

@raajtram that would work, but unfortunately not all websites are built like that (I wish they were)

authors: Booligoosh raajtram

repo: ankit/stylebot


text:
Add tic-tac-toe game in cpp

Add tic-tac-toe game in cpp along with a readme to expaining it

HI ankitapuri, can you assign me to this? I'd love to tackle this since I haven't used C++ in a project yet!

authors: andrewsnapz ankitapuri

repo: ankitapuri/DSA-guide


text:
🛑 SQCP is down

In 7c1f264, SQCP (https://sqcp.mikrotik24.duckdns.org) was down:

HTTP code: 0
Response time: 0 ms

Resolved: SQCP is back up in 42da46c after 31 minutes.


text:
Add custom html.

Hello!
I want to add custom HTML where the cursor is. How to do it?
Thank you!

Please ask such questions at
https://github.com/Alex-D/Trumbowyg

Ок. How I get access to $('#my-editor') ?
$('#my-editor').trumbowyg('execCmd', {
	cmd: 'insertText',
	param: 'TextToInsert',
	forceCss: false,
});```

You can add a ref="editor" to component and then access it like
// In your component
this.$refs.editor.el.trumbowyg();

Thanks @ankurk91


text:
load different runners file with a cli option

replacing the default runners.toml file by loading a different one as a command line option

closed by #18

repo: anna-singleton/runfast


text:
🛑 Pedproject is down

In 6be7b24, Pedproject (https://педпроект.рф) was down:

HTTP code: 0
Response time: 0 ms

Resolved: Pedproject is back up in 5a3ca8d after 13 minutes.

repo: ano-pedproject/repo


text:
Notifications

Description
Notifications are needed to communicate various events to the user. It is local to the front and should be able to be triggered from the actions.
It should contain the following features, even though all might not be needed initially:

can be triggered from actions
can be dismissed from the actions
2.3 it should keep a reference to the action that triggered it so that the same action can then dismiss it
can be dismissed after a time out if not dismissed programmatically
can have a fixed defined display time
can be dismissed by the user
there can be multiple of these at the same time in the UI, and they will stack nicely.
has 3 types: info, warning, error
can have arbitrary content and accept callbacks

Thoughts
Associating actions to notifications (2.3 above)
So the typical use case would be that a notification might be triggered bydoSomething.pending action. And it would be then dismissed by doSomething.fulfilled, doSomething.rejected, or by time out. For dismissing it, it should likely live in redux and contain a reference to the action that triggered it. That could be done by storing the requestId: "<requestIdOfAction>" of the action. That ID can be picked up in actions from createAsyncThunk function's options.requestId or in reducer from addCase(doSomething.fulfilled, (state, action) => action.meta.arg.requestId

maybe it can be like a queue where they appear from the top
and disappear by animating opacity to 0

it could look something like this
import { createNotification, dismissNotificationWithId, NotificationType } from "components/notifications";

// this is an action that creates a new account, it takes a few seconds and can fail
export const createShieldedAccount = createAsyncThunk<>(NAME, async(newAccountDetails: DataType, thunkApi) => {
    // first we define the notification
    const notificationAboutCreatingNewAccount = {
        title: "Creating a new account",
        description: "description",
        notificationId: thunkApi.requestId,
        type: NotificationType.Info,
        timeOutInSeconds: 0, // it will not disappear by it's own
    }

    // then we dispatch it, this causes a visible element to be created and added to the DOM
    thunkApi.dispatch(createNotification(notificationAboutCreatingNewAccount));

    // then we do some long lasting async stuff trying to create the account
    try {
        // it all succeeded and we are about to pass the new data to reducer,
        // so lets remove that notification
        thunkApi.dispatch(dismissNotificationWithId(thunkApi.requestId));

        // now we return the data if the new account to reducer
        return payload;
    } catch (error) {
        // it failed, so lets create a new notification informing the user

        // we do not need to define time out as it will just use the default time out and disappear in x seconds
        // we also do not pass notificationId as we are not going to dismiss it from the action that created it
        const notificationAboutCreatingNewAccount = {
            title: "Creating account failed",
            description: `this and ${error} happened`,
            type: NotificationType.Error,
        }

        // now we can dispatch it
        thunkApi.dispatch(createNotification(newNotificationInformingAboutFailure));

        // and remove the 1st notification
        thunkApi.dispatch(dismissNotificationWithId(thunkApi.requestId));
        return Promise.reject("error");
    }
});

repo: anoma/namada-interface


text:
Are there any plans for further documentation?

Thanks for putting up this awesome project! I'm just learning the ins and outs of Webpack and React and this boilerplate has the exact tools I am looking for to get started. I'd love to be able to understand what the various pieces are doing, how it all works together, why some of the tools/patterns were chosen, how someone might go about customizing this to build out their own project, etc. Are there any plans to build out more detailed documentation or tutorials? Thanks again!

this would be a great idea!

I think that would be useful - I have been exploring some of the more complex boilerplates out there such as the Universal/Isomorphic ones and this strips things down to purer react and redux, which is welcome by my book. So you can kind of learn from them and work it out here..... but that said, some more docs would be lovely :-)

Thanks mates. I'll try to do a small but useful docs, asap.

authors: keske nickeblewis nivek005 thecodingwhale

repo: anorudes/redux-easy-boilerplate


text:
Getting id's of drawn SVG line

There are multiple leader lines drawn between multiple divs and if a user wants to delete a single line or highlight a single line on clicking, how to track the Id of that line

Hi @udit9412, thank you for the comment.
Try this:
const
  line1 = new LeaderLine(elmA, elmB),
  elmLine1 = document.querySelector('body>.leader-line:last-of-type'),

  line2 = new LeaderLine(elmC, elmD),
  elmLine2 = document.querySelector('body>.leader-line:last-of-type');

Note that this is not supported by the library.

Thank you so much for the solution. So as per current suggestion I applied that to register an eventListner to trigger a function at call but again function was not triggered on clicking of the line
let element =document.querySelector('body>. leader-line:last-of-type').addEventListener("click", (event) {
alert(s(event.target.nodeName.toUpperCase() element );
console.log("Ciciked")
});

Your code has some problems.
For example, the variable element has nothing because addEventListener method returns nothing. And also, a function must be event => {} if you intended to write an arrow function.
And more...
Maybe you have to learn JavaScript and rewrite your code.
For example: https://jsfiddle.net/sbvnh30g/

Thanks for the reply!. Yeah I missed the syntax while writing code in GitHub while it was already an arrow function in the code. And with that particular line I removed variable declaration as it will never return anything but the point is the function was not getting triggered and after some time, while using dev tools, I noticed that "pointer-events" was set to none!important by default which was creating the issue. Now it's solved and thanks for the support

:smile:

repo: anseki/leader-line


text:
Test test_command_init_scenario with delegated

Instead of using podman or docker to test this long scenario, switch to use
only delegated for testing it.
Depends-On: https://review.opendev.org/#/c/707078/

recheck

recheck

recheck

authors: pabelanger ssbarnea

repo: ansible-community/molecule


text:
Unquote versions in precommit

Cleanup some quoteing

simple change, self approving

repo: ansible/ansible-creator


text:
[AAP-7174] Database defined default user roles

Drop configuration parameter EDA_DEFAULT_USER_ROLE in favor of database defined default user roles.
The roles database tables now has new is_default field. When is_default set to True, a role is automatically assigned to a user at user creation or registration.
Implements: https://issues.redhat.com/browse/AAP-7174
Testing instructions

Create an empty database

Execute:
python scripts/load_data.py tools/initial_data.yml

Login as root:
TOKEN=$(http -f POST http://localhost:9000/api/auth/bearer/login username=root@example.com password=secret | jq -r .access_token)

Check roles, a new is_default field must be included in response.
http -A bearer -a "$TOKEN" http://localhost:9000/api/roles
[
    {
        "description": "Has full access to all resources",
        "id": "4ca9cd32-e11e-4634-875e-4acf7a5682e1",
        "is_default": false,
        "name": "admin"
    },
    ...

Check your roles, you should see default role in the list of roles.
http -A bearer -a "$TOKEN" http://localhost:9000/api/users/me/roles
[
    {
        "description": "Default role, that is applied to all users",
        "id": "12e9b549-e1eb-40cb-b84b-f289614439af",
        "is_default": true,
        "name": "default"
    }
]

Login as any other user, repeat steps 3 and 4.

@cutwater Just a small comment on this; I believe the PR description shouldn't go as part of commit message, especially if the description is too large. Before merging PRs, we could edit and shorten the description into a brief summary.

@Dostonbek1 @cutwater I Agree. This is configured at repo level. It can be just the title, or the commit message. We can discuss it the next sync meeting

@Dostonbek1 Thank you for this remainder. I forgot to remove the testing instructions from the commit message.

authors: Alex-Izquierdo Dostonbek1 cutwater

repo: ansible/eda-server


text:
feat: database module improvements

Description
As the title.
Small database modul improvements I'm doing while I try to fix #3248
Issue linked
Related #3248
Checklist

[x] I have visited and read Develop PyMAPDL.
[ ] I have tested my changes locally
[x] I have added necessary documentation or updated existing documentation.
[x] I have followed the PyMAPDL coding style guidelines.
[x] I have added appropriate unit tests that also ensure the minimal coverage criteria.
[x] I have reviewed my changes before submitting this pull request.
[x] I have linked the issue or issues that are solved to the PR if any.
[x] I have assigned this PR to myself.
[x] I have marked this PR as draft if it is not ready to be reviewed yet.
[x] I have made sure that the title of my PR follows Commit naming conventions (e.g. feat: adding new MAPDL command)

Pinging @clatapie for feedback and review.

repo: ansys/pymapdl


text:
Use tree component onclick event error(模板中使用Tree组件，onclick事件中参数转换失败)

组件事件是 OnClick

@ElderJames 不好意思，提交了错误的Issues

authors: ArkChangcheng ElderJames

repo: ant-design-blazor/ant-design-pro-blazor


text:
vtabs组件左侧tab滑动至底部以后切换不生效

组件

Vtabs
基础库版本

[ ] 1.x
[ √ ] 2.x

设备机型
手机系统

[√ ] iOS
[ ] Android
[ ] HarmonyOS

APP

组件库版本

预期行为

选中后不自动切换回原来的选项
复现步骤

复现 demo

0.0.10已修复

authors: gotSomeCool miaodongqing

repo: ant-design/ant-design-mini


text:
💄 UI: update td font-size to antd less var

pro-table 字体大小应该跟 antd 保持一致

Codecov Report

Merging #690 into master will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master     #690   +/-   ##
=======================================
  Coverage   17.22%   17.22%
=======================================
  Files          21       21
  Lines        1155     1155
  Branches      378      401   +23
=======================================
  Hits          199      199
+ Misses        956      954    -2
- Partials        0        2    +2

Impacted Files
Coverage Δ

src/Table.tsx
20.00% <0.00%> (ø)

src/component/columnSetting/index.tsx
5.61% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update df4fc21...42d3058. Read the comment docs.

authors: Deturium codecov-commenter

repo: ant-design/pro-table


text:
Collapsable tree of categories

subj.

Save/restore collapsed categories on save
collapsed by default (optionally)

Good improvement :+1: , and I've already had some thoughts about it.
Kdbx format supports storing collapsed/expanded state but there's ux trouble. As there is no expand indication icon (+/-, or >, on the left of list), it will be unclear that a group is collapsed and has some groups inside. So, we can open a file with collapsed groups only if the user have already opened it and collapsed them by himself.
So, I'm still thinking, how to make this available.
Collapsed by default: wontfix this. If we have a possibility to store collapsed/expanded state, just collapse them and save.

Changed the title to better reflect the issue: the they are collapsible for now but not saved

Deployed to beta.keeweb.info, will be available in the next release

authors: KhodeN antelle

repo: antelle/keeweb


text:
consistent-chaining false positives

Describe the bug
The bug pertains to the new consistent-chaining rule. As shown in the documentation, the following should be correct
const foo2 = []
  .map(x => x + 'bar')
  .filter(Boolean)

However, the following code returns an error
const x = {foo: 1, bar: 2 }
const result = Object.keys(x)
  .reduce((acc, key) => ({ ...acc, ...x[key] }), {});

It looks like the rule explicitly expects the first property in the chain to be a variable. If its a function, it breaks.

Reproduction
https://github.com/MrVauxs/antfu-repro
System Info
System:
    OS: Windows 11 10.0.22631
    CPU: (12) x64 AMD Ryzen 5 3600 6-Core Processor
    Memory: 12.42 GB / 31.93 GB
  Binaries:
    Node: 22.6.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.8.3 - C:\Program Files\nodejs\npm.CMD
    bun: 1.1.12 - ~\.bun\bin\bun.EXE
  Browsers:
    Edge: Chromium (127.0.2651.74)
    Internet Explorer: 11.0.22621.3527

Used Package Manager
npm
Validations

[X] Follow our Code of Conduct
[X] Read the Contributing Guide.
[X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
[X] Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
[X] The provided reproduction is a minimal reproducible of the bug.

Contributions

[ ] I am willing to submit a PR to fix this issue
[ ] I am willing to submit a PR with failing tests (actually just go ahead and do it, thanks!)

Also, properties on this should also not be wrapped
const result = this.userList
  .filter(user => user.name.startWith('T'))
  .map(user => user.phoneNumber)

https://github.com/antfu/eslint-plugin-antfu/commit/10e9920e51d691635016921dc72700e2624726c0 should fix it. thanks

authors: MrVauxs antfu subframe7536

repo: antfu/eslint-plugin-antfu


text:
Some thoughts on nrm and other naming conflicts

First of all, thank you very much for this project, it has been very convenient for me, but of course I also encountered the problem of nrm naming conflicts, whenever I want to uninstall a package, I still need to determine the current package manager, considering how often npm uninstall is used, I think I need to discuss this issue.
When I read #33, my first thought was to customize the alias in .nirc, but that didn't seem to work when I tried to dynamically generate the bin file.
idea: read the configuration before install and generate the bin file, add it to directories.bin.
Reference:

preinstall: https://docs.npmjs.com/cli/v8/using-npm/scripts#life-cycle-scripts

directories.bin: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#directoriesbin

bin-links: https://github.com/npm/bin-links

Similar Questions: https://stackoverflow.com/questions/67665230/can-i-add-files-to-directories-bin-dynamically-through-npm-script-before-npm-pro

After I researched and tried the above options with no results, I had to post the question to the community for further discussion.
If there is no other solution, is it possible to change nrm to nun or some other name ...😂...

I agree

@antfu I've seen the closed tickets and comments regarding nrm and it makes sense why you removed it due to conflicts.
But was there ever a replacement? How do I remove a package with ni??? I can't find a working command for it anywhere.
I don't even mind it being a long command, anything beats checking the package manager used manually and typing pnpm remove xxx

Changed to nun, see #69 .

authors: HongxuanG MarkLyck muzaisimao

repo: antfu/ni


text:
Add support for display_override

This change adds type support for the display_override manifest member.

@michaelhue thx, just in time

authors: michaelhue userquin

repo: antfu/vite-plugin-pwa


text:
Bump 'critters' dependency to 0.0.20

Clear and concise description of the problem
A new version of Critters has been released:
https://github.com/GoogleChromeLabs/critters/releases/tag/0.0.20
However it's throwing peer dependency warnings in npm:

Suggested solution
Bump critters dependency version for vite-ssg
Alternative
No response
Additional context
No response
Validations

[X] Follow our Code of Conduct
[X] Read the Contributing Guide.
[X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Same issue for me, its blocking me updating to the latest version of vite-ssg
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: vite-ssg@0.23.2
npm ERR! Found: critters@0.0.20
npm ERR! node_modules/critters
npm ERR!   dev critters@"0.0.20" from the root project

Bumpped.

authors: antfu binaryfire rezelute

repo: antfu/vite-ssg


text:
Intellisense doesn't work.

Describe the bug
I can see the icon inside the attribute, but the intellisense doesn't work. Any idea? I'm using a Nuxt 3 project with NuxtLab UI.
<UButton icon="i-heroicons-magnifying-glass" />
My file settings.json is empty during test.
Reproduction
local
System Info
System:
    OS: macOS 12.6.8
    CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
    Memory: 302.67 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.16.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.8.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 115.0.5790.114
    Safari: 16.6

Used Package Manager
yarn
Validations

[X] Follow our Code of Conduct
[X] Read the Contributing Guide.
[X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
[X] Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
[X] The provided reproduction is a minimal reproducible of the bug.

We temporarily close this due to the lack of enough information.
Please provide a minimal reproduction to reopen the issue.
Thanks.

Why reproduction is required

I'm having the same issue... If I rollback to v0.5.4 then the intellisense typeahead works again.
To reproduce:

In a compatible file/attribute type a prefix and then : - this normally triggers the typeahead for that particular iconset.

In v0.6.0 and 0.6.1 nothing happens. However, if you happen to type a valid icon name it does render.

v0.6.0 & 0.6.1

v0.5.4

+1

authors: antfu craigerskine julien-blanchon wallysonn

repo: antfu/vscode-iconify