UI5 - управляющий форматтер выполняется слишком рано, прежде чем данные будут загружены в модель - PullRequest
0 голосов
/ 26 июня 2019

У меня есть веб-приложение, которое после входа в систему отображает целевой экран с панелью навигации слева.Кроме того, во время события onInit я вызываю getUserData () , которая собирает дополнительные данные о пользователе (например, роли и сохраняет их в модели).Эта навигация имеет тип sap.tnt.NavigationListItem и загружается из модели (данные жестко закодированы в App.controller.js ).В App.view.xml это выглядит так:

<tnt:NavigationListItem text="{appView>title}" 
items="{path: 'appView>items', templateShareable: true}"
visible="{path: 'appView>neededRole', formatter:'.myFormatter'}"> 

Теперь я хотел бы внести улучшение - , чтобы некоторые элементы в списке навигации отображались только дляпользователи с достаточными ролями .Как вы можете видеть выше, Я установил форматер для свойства 'visible' NavigationListItem.Он проверяет роль, необходимую для отображения NavigationListItem («необходимая роль»), сравнивает ее с массивом ролей, назначенных пользователю, и, если есть совпадение, показывает пункт меню

myFormatter: function(role) {
    const oModel = this.getView().getModel('appView');
    return oModel.oData.userData.roles.some(x => x.roleId === role);
    }

Проблема заключается вчто когда функция myFormatter запущена, getUserData () еще не завершена и модель еще не содержит необходимый массив ролей пользователя - в качестве причины все пункты меню скрыты.Чего мне нужно добиться, так это убедиться, что MyFormatter запускается ТОЛЬКО ПОСЛЕ того, как getUserData () завершил работу (и хотя myFormatter будет выполняться неоднократно, getUserData должен запускаться только один раз).Как мне этого добиться?getUserData () является асинхронным, и независимо от того, помещаю ли я его в onInit или beforeRendering, он завершается только после того, как myFormatter соберет пустой массив из модели.

Спасибо миллион

1 Ответ

0 голосов
/ 26 июня 2019

Ваш форматтер запустится первым, когда представление инициализируется, это часть жизненного цикла. Затем он будет запускаться каждый раз, когда запись 'needRole' явно (через model.setProperty) изменяется

В вашем коде кажется, что ваш форматировщик фактически использует другие данные из модели: 'role' Таким образом, вы можете просто привязать ваш форматер к обеим записям модели:

<tnt:NavigationListItem
  text="{appView>title}" 
  items="{
    path: 'appView>items',
    templateShareable: true
  }"
  visible="{
    parts: ['appView>neededRole', 'appView>/userData/roles'],
    formatter:'.myFormatter'
  }"> 

и измените ваш форматер на

myFormatter: function(role, roles) {
  return (roles || []).some(x => x.roleId === role);
}

Тогда ваш модуль форматирования сработает, когда роль или роли будут изменены в модели.

В качестве примечания: средство форматирования предназначено для форматирования данных, а не для вычислений. Лучшим вариантом было бы напрямую создать запись 'entryVisible' в модели, которую вы могли бы затем связать с вашим NavigationListItem (я знаю, что форматировщики выполняют эту работу, но они также вызывают много повторных рендерингов, которые вам не нужны)

...