Передача данных в mat-меню

#angular #angular-material

#angular #angular-материал

Вопрос:

Мое «потрясающее» меню:

 <mat-menu #appMenu="matMenu">
  <ng-template matMenuContent let-myobject="myobject">
    <button mat-menu-item>Delete {{myobject.name}}</button>
    <button mat-menu-item>Smth else</button>
  </ng-template>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="appMenu" [matMenuTriggerData]="{myobject: myobject}">
   <mat-icon>more_vert</mat-icon>
</button>
  

Первый вопрос в том, нормально ли это? Написал следующую документацию, но let-myobject="myobject" и {myobject: myobject} выглядит как накладные расходы (?)

Второй вопрос заключается в том, хочу ли я вычислить некоторые данные на основе myobject — как я это делаю? Я хочу, чтобы это было вычислено непосредственно перед открытием menu.

[matMenuTriggerData]="getData(myobject)" — не удается выполнить эту или подобную работу

<ng-template matMenuContent let-data="getData(myobject)"> — также не удается выполнить эту или подобную работу

Я знаю, что могу заменить ng-template здесь компонентом, но тогда, например, для 10 пунктов меню мне нужно будет выполнить 10 выходных данных в этом компоненте. (? или я не могу …)

Комментарии:

1. Иногда синтаксис angular действительно кажется накладным 🙂 Однако вам следует избегать передачи метода любым свойствам ввода, поскольку они будут вызываться при каждом обнаружении изменений, влияющих на производительность. Что вы можете сделать здесь, так это прослушать menuOpened событие директивы MatMenuTrigger, а затем вычислить в функции-обработчике и установить правильную ссылку на matMenuTriggerData.

Ответ №1:

Вы, безусловно, можете передать объект в mat-menu с помощью matMenuTriggerData директивы. Этот объект может содержать одно значение, другой объект или даже массив значений или объектов. Вот как я это решил:

Моя задача заключалась в следующем: я хотел динамически создавать список пунктов меню ( mat-menu-item ) на основе содержимого массива. Как мне удалось передать этот массив объектов моему mat-menu ?

В вашем классе компонентов вы можете определить массив объектов:

     export class MyComponent implements OnInit {
      menuData: any;

      ngOnInit() {
        this.menuData = {
          menuItems: [
            {code: '1', name: 'first'},
            {code: '2', name: 'second'}
          ]
        };
      }
    }
  

Обратите внимание, что объект, который я передам в matMenuTriggerData директиву кнопки, которая открывает mat-menu содержимое, является вызываемым элементом данных menuData . Этот элемент имеет только одно свойство, которое представляет собой массив объектов. Они представляют фактические пункты меню, которые я хочу отобразить в своем шаблоне. Шаблон показан ниже:

     <mat-menu #app-menu="matMenu">
      <ng-template matMenuContent let-aliasMenuItems="menuItems">
        <button mat-menu-item *ngFor="let item of aliasMenuItems">
          Item {{item.code}}: {{item.name}}
        </button>
      </ng-template>
    </mat-menu>
    <button mat-icon-button [matMenuTriggerFor]="app-menu" [matMenuTriggerData]="menuData">
      <mat-icon>more_vert</mat-icon>
    </button>
  

Позвольте мне объяснить, что происходит в шаблоне: кнопка, определенная в нижней части шаблона, была связана с mat-menu вызываемой 'app-menu' . Это делается путем ввода [matMenuTriggerFor]="app-menu" .

Следующее, что мы делаем, это передаем данные элемента компонента в mat-menu через эту директиву: [matMenuTriggerData]="menuData" . mat-menu Экземпляр, который мы назвали app-menu , теперь может извлекать содержимое данных этого элемента.

Как вы можете видеть, <ng-template> обращается к свойству 'menuData' , которое мы назвали 'menuItems' . <ng-template> Добавляет указатель или псевдоним к этому свойству (вызываемому aliasMenuItems ), вот так: <ng-template let-aliasMenuItems="menuItems"> . Теперь мы можем перебирать определенный нами массив пунктов меню внутри <ng-template> .

В моем примере я создаю <button mat-menu-item></button> элемент для каждого объекта элемента меню, который существует в menuData.menuItems массиве моего компонента, вот так:

     <button mat-menu-item *ngFor="let item of aliasMenuItems">
      Item {{item.code}}: {{item.name}}
    </button>
  

Я надеюсь, вы найдете этот ответ полезным.

Комментарии:

1. Просто хотел упомянуть, что вы также можете вызвать метод в вашем компоненте, который возвращает объект, содержащий тот же массив: [matMenuTriggerData]=»getMenuData()».

2. Отдаю должное такому длинному ответу… Но, похоже, вы не поняли мою проблему — представьте, что у вас есть 100 matMenuTriggerFor на странице для одного меню — как заставить это работать, не создавая 100 объектов для каждого?

3. Итак, вы хотите повторно использовать этот единственный элемент mat-menu внутри вашего шаблона и заставить его получать отдельные наборы данных (пункты меню) с нескольких разных кнопок? Если вы нажмете на кнопку 1, вы хотите использовать атрибут matMenuTriggerData для отправки одного списка пунктов меню элементу mat-menu, а с помощью кнопки 2 вы отправите ему другой список пунктов меню? В этом случае я бы поместил mat-menu внутри отдельного компонента, который может получать массив пунктов меню через свойство @Input. Тогда вы могли бы использовать это следующим образом в своем шаблоне: <my-menu [MenuItems]=»listOfItemsFromModel»></my-menu>.

4. Пожалуйста, дайте мне знать, если хотите, чтобы я показал вам пример того, как сделать то, что я предлагаю в моем предыдущем комментарии. Я с удовольствием обновлю свое предложение выше. 🙂

5. Проверьте эту ссылку в качестве примера stackblitz.com/edit/angular-lekzuk?file=src/app /…