简体   繁体   中英

angular material dynamic menu content not showing up

I am a newbie to angular, and am working on getting a component in place that includes a text input field that, once more than 3 characters are entered, makes a service call to search data in a database and return an array of items that are used in a pop-up menu for selection.

I have the service in place and returning appropriately, and the menu item pops up when I want it to and goes away when I want it to, but I can't get the menu to come up with any content. It always pops up as an empty box. I was able to get mat-menu working elsewhere in my application as a context menu and that appears fine, so I'm not sure what I'm missing on this one. Anyone have any idea what's wrong?

template code:

  <div>
    <mat-menu #searchResultMenu="matMenu" yPosition="above" *ngIf="searchResults.length > 0">
      <ng-template matMenuContent let-searchResults="searchResults">
        <button mat-menu-item *ngFor="let sritem of searchResults" (click)="findAndSelect(sritem)">
          {{sritem.displayName}}
        </button>
      </ng-template>
    </mat-menu>

    <!-- div below is really just there so I can open/close the menu 
         in typescript code rather than with a visual UI component action. 
    -->
    <div #menuTrigger [matMenuTriggerFor]="searchResultMenu" [matMenuTriggerData]="searchResults"></div>

    <mat-form-field>
      <mat-label>Search String</mat-label>
      <input matInput type="text" [value]="searchString" (input)="searchStringChanged($event)">
      <button *ngIf="searchString" matSuffix mat-icon-button aria-label="Clear" (click)="searchString=''">
        <mat-icon>clear</mat-icon>
      </button>
    </mat-form-field>
  </div>

typeScript code:

@ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger;
public searchResults: SearchResultItem[];

* * *

  searchStringChanged(ev:Event) {
    this.searchString = <string>((<any>ev.target)?.value);

    if (this.searchString?.length > 3) {
      this.myservice.getSearchResults(this.searchString).subscribe(data => {
        <!-- prove to myself I'm getting a result set: -->
        console.log("search returned results: ", data);

        if (data.length > 0) {
          this.searchResults = data;
          this.menuTrigger.menuData = this.searchResults;
          this.menuTrigger.openMenu();
        }
      });
    }
  }
 
  clearSearchString() {
    this.searchString = "";
    this.searchResults = [];
    this.menuTrigger.closeMenu();
  }

  findAndSelect(sritem: SearchResultItem) {
    console.log("Searching for item named: ", sritem.displayName);
    this.menuTrigger.closeMenu();
  }

* * *

searchResult is an array of SearchResultItem objects returned from my service, and I've verified it is populated when the menu appears, and that each object contains a parameter called 'displayName' that is a string.

Thanks in advance.

Additional info:

what I see in the UI: UI screenshot

what I see in the debug console returned from my service: debug console screenshot

删除 let-searchResults="searchResults" ,它将起作用

While the above answered my original question, I had some other run-time errors that were popping up even though the UI was functioning fine. I eventually tracked them down and cleaned up my original post to what is below. Just thought I would add this in case anyone else was trying to copy the code I originally posted...use below instead. Basically, I removed the ngIf from my mat-menu tag and updated components accordingly in both the template and typescript, along with the original problem solution change.

Many thanks to Faizal for his comments/answer.

template code:

  <div>
    <mat-menu #searchResultMenu="matMenu" yPosition="above">
      <ng-template matMenuContent>
        <button mat-menu-item *ngFor="let sritem of searchResults" (click)="findAndSelect(sritem)">
          {{sritem.displayName}}
        </button>
      </ng-template>
    </mat-menu>

    <div style="visibility: hidden; position: fixed" [matMenuTriggerFor]="searchResultMenu">
    </div>

    <mat-form-field>
      <mat-label>Search String</mat-label>
      <input matInput type="text" [value]="searchString" (input)="searchStringChanged($event)">
      <button *ngIf="searchString" matSuffix mat-icon-button aria-label="Clear" (click)="searchString=''">
        <mat-icon>clear</mat-icon>
      </button>
    </mat-form-field>
  </div>

typescript code:

@ViewChild(MatMenuTrigger) searchResultMenu: MatMenuTrigger = <MatMenuTrigger><unknown>null;
public searchResults: SearchResultNode[] = [];

* * *

  searchStringChanged(ev:Event) {
    this.searchString = <string>((<any>ev.target)?.value);

    if (this.searchString?.length > 3) {
      this.myservice.getSearchResults(this.searchString).subscribe(data => {
        <!-- prove to myself I'm getting a result set: -->
        console.log("search returned results: ", data);

        if (data.length > 0) {
          this.searchResults = data;
          this.searchResultMenu.menuData = this.searchResults;
          this.searchResultMenu.openMenu();
        }
      });
    }
  }
 
  clearSearchString() {
    this.searchString = "";
    this.searchResults = [];
    this.searchResultMenu.closeMenu();
  }

  findAndSelect(sritem: SearchResultItem) {
    console.log("Searching for item named: ", sritem.displayName);
    this.searchResultMenu.closeMenu();
  }

* * *


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM