angular-devtools icon indicating copy to clipboard operation
angular-devtools copied to clipboard

Problem with components that are created with component factory resolver

Open ayberkaltuntabak opened this issue 4 years ago • 9 comments

Description: First of all, I am very happy to hear that we have official dev tool support. The bug is that I can't inspect components which i init with component factory resolver in mat-drawer-content component at components side of dev tools. ...

Angular Devtools version (required): 1.0.0

Angular version (required): 11.0.9

Date: 19.05.2021 GMT +03:00

OS: Windows 10 Home 10.0.19042

Demo test application:

  • Git repository for demo app showing the issue (optional but very helpful for difficult issues).
  • If a code snippet will completely show the issue, please include it.

Typescript file.


import { CustomButtonComponent } from './../custom-button/custom-button.component';
import { Component, Input, OnInit, OnChanges, ViewChild, ViewContainerRef, ComponentFactoryResolver, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { Menu } from 'src/models/menu/Menu';
import { ButtonConfig } from 'src/models/ButtonConfig';
import { UserManagementComponent } from '../user-management/user-management.component';
import { ActivityComponent } from '../activity/activity.component';
import { DashboardComponent } from '../dashboard/dashboard.component';
import { PolicyComponent } from '../policy/policy.component';
import { UserSettingsComponent } from 'src/app/user-settings/user-settings.component';
import { AlertsComponent } from 'src/app/alerts/alerts.component';

@Component({
  selector: 'app-custom-sidenav-menu',
  templateUrl: './custom-sidenav-menu.component.html',
  styleUrls: ['./custom-sidenav-menu.component.scss']
})
export class CustomSidenavMenuComponent implements OnInit {
  @ViewChild("buttonArea",{read:ViewContainerRef}) buttonArea:ViewContainerRef | any;
  @Input()
  menuCollection!:Menu[] | any;
  @Output()
  buttonSelected = new EventEmitter<any>();
  cleanMenuCollection : Menu[] | any
  buttonConfig: never[] | any;
  componentMap!:any
  selectedMenu: ButtonConfig;
  constructor(private componentFactoryResolver:ComponentFactoryResolver,private cdr : ChangeDetectorRef) {
    this.componentMap  = {
      "Users":UserManagementComponent,
      "Activity":ActivityComponent,
      "Policy":PolicyComponent,
      "Dashboard":DashboardComponent,
      "User Settings":UserSettingsComponent,
      "Alerts": AlertsComponent
    }
  }

  ngOnInit(): void {
  }
  ngOnChanges(menuCollection:Menu[] | any){


  }

  ngAfterViewInit(){
    this.cleanMenuCollection = [];
    this.menuCollection.forEach((menuTemp:Menu) => {
      let foundMenuItemsInBefore :any = this.cleanMenuCollection.find((data :Menu | any) => {
        if(menuTemp.type ==  data.type){
          return data;
        }
      })
      if(foundMenuItemsInBefore == undefined){
        this.cleanMenuCollection.push(menuTemp)
      }
    });


    this.createButtons();
  }
  createButtons() {
    this.buttonArea?.clear();
    this.buttonConfig = this.cleanMenuCollection.map((data:Menu)=>{
      let key :any = this.componentMap[data.type];
      let obj = {icon:data.icon,buttonClass:"btn-transparent",status:"passive",click:(event:any) => this.clickOnMenu(event),text:data.type,menuComponent:key}
      let compRef = this.componentFactoryResolver.resolveComponentFactory(CustomButtonComponent);
      let comp = this.buttonArea.createComponent(compRef);
      comp.instance.config = obj
      return obj
    })
    let dashboardButton=this.buttonConfig.find(config => config.text == 'Dashboard');
    dashboardButton.buttonClass = "btn-transparent menu-active"
    this.buttonSelected.emit(dashboardButton.menuComponent)
    this.cdr.detectChanges();
  }
  clickOnMenu(event:any){
    this.buttonConfig=this.buttonConfig.map((menuItem:ButtonConfig)=>{
      if(event.config != menuItem){
        menuItem.buttonClass = 'btn-transparent';

      }else{
        menuItem.buttonClass = "btn-transparent menu-active"
        if(this.selectedMenu?.text != menuItem.text){
          this.selectedMenu = menuItem
          this.buttonSelected.emit(menuItem.menuComponent)
        }
      }
      return menuItem
    })

  }
  // this.navbarButton = { icon: 'fas fa-bars', buttonClass: 'btn-transparent', status: "passive", click: (event: any) => this.navbarClick(event) }
  getKeyByValue(object: { [x: string]: any; }, value: any) {
    return Object.keys(object).find(key => object[key] === value);
  }
}

Html File

<div class="application-container w-100 h-100">
  <mat-drawer-container class="example-container h-100 w-100">
    <mat-drawer class="mat-container" #sidenav mode="side" style="width: 15%;">
      <div class="d-flex flex-column align-items-center justify-content-between p-2 overflow-hidden">
        <div class="header w-100">
          <span class="header-text fs-4 w-100">
            {{this.user?.honeypot?. name}}
          </span>
        </div>
        <ng-container #sidenavArea></ng-container>
      </div>
    </mat-drawer>
    <mat-drawer-content class="component-area">
      <ng-container #componentArea></ng-container>
    </mat-drawer-content>
  </mat-drawer-container>
</div>

Description of issue:

Capture

As you may see that components that should be produced ,are not shown.

I appericiate your attention on this spesific problem in advance.

ayberkaltuntabak avatar May 18 '21 22:05 ayberkaltuntabak

Hey @AyberkAltuntabak, that's a known issue in version 11 and older. If you update to v12, the issue should be gone! We introduced new debugging APIs which help us find the render tree more accurately.

I'll keep the issue open for now and pin it to make sure other folks facing the same issues find the response.

mgechev avatar May 19 '21 12:05 mgechev

FYI, labeling as a P3 because this should be fixed by Angular v12. Let me know if that's not the case.

mgechev avatar May 19 '21 12:05 mgechev

@mgechev Thanks for your response. I wish good luck for developing dev tools.

ayberkaltuntabak avatar May 19 '21 13:05 ayberkaltuntabak

Issue confirmed here also. Just tried with Angular 12 and it seems better @mgechev However, update of the dev tools panel is not smooth. To see "new nodes / components" I sometimes have to expand / collapse an existing node. I guess that's because we have a lot of components?

CheetahDev avatar Jun 08 '21 09:06 CheetahDev

Issue confirmed here also. Just tried with Angular 12 and it seems better @mgechev However, update of the dev tools panel is not smooth. To see "new nodes / components" I sometimes have to expand / collapse an existing node. I guess that's because we have a lot of components?

@CheetahDev If possible could you open a new issue documenting your concern about the dev tools panel not being smooth? I'm interested in ways we could improve the user experience for everyone. Thanks.

AleksanderBodurri avatar Jun 11 '21 23:06 AleksanderBodurri

I see my Angular 12 dynamic components in the tree, but the selector for them isn't shown.

image

Every one of the DIVS, ARTICLEs shown here is a dynamic component, such as 'DynamicGridComponent', 'DynamicFeatureComponent', 'MarkdownComponent' etc.

I realize it may not be possible to show the directives applied as for other component - but if there was a way to see the component class name, or even expose something like a __componentDebugName property that could be displayed in the tree it would be very useful. The best I can do is create such a property and I can see it in the property panel - it would just be really nice to see it in the tree.

simeyla avatar Jul 08 '21 19:07 simeyla

I realize it may not be possible to show the directives applied as for other component - but if there was a way to see the component class name, or even expose something like a __componentDebugName property that could be displayed in the tree it would be very useful. The best I can do is create such a property and I can see it in the property panel - it would just be really nice to see it in the tree.

You could use $ng0 in the console. Are you using div as a selector for your components?

mgechev avatar Jul 08 '21 21:07 mgechev

@mgechev Thanks for the reply. Yes all those div, article, figure and section nodes are dynamic components - not just HTML. The only exception is the 'picture' tag which is inside my DynamicImageComponent (figure), but the picture tag and image directive are inside the template so they're able to be shown in the tree.

My goal really is to be able to find something in the tree quickly - and since this whole component of my application is dynamic it's just a bit harder. Would be great to hook into it somehow, but not the end of the world if not possible.

simeyla avatar Jul 09 '21 03:07 simeyla

@simeyla would you open a feature request with your ask for richer discovery functionality? This seems unrelated to the problem described here for versions prior to v12.

mgechev avatar Jul 09 '21 18:07 mgechev