SapUI5: Играем с моделью.

Зачастую нам необходимо хранить, передавать, использовать какие-либо данные внутри SapUI5 приложения.

Например, мы хотим сделать небольшой календарь для трех лет, а отображать мы будем только один год.

Для этого нам нужны:

  • Предыдущий год.
  • Текущий год.
  • Следующий год.

Сохранить их и при каком-то действии (например, клик на кнопку) помечать какой год у нас выбран.

Лучший способ это сделать — создать модель:

Получим текущий год, рассчитаем предыдущий и следующий.
Создадим массив и установим модель.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Получаем текущий, предыдущий и следующий год
var d = new Date();
var currentYear = parseInt(d.getFullYear());
var prevYear = parseInt(d.getFullYear() - 1);
var nextYear = parseInt(d.getFullYear() + 1);
 
//Создаем массив
var year = {
 "items": [{
   "key": prevYear,
   "load": false
           }, {
   "key": currentYear,
   "load": false
           }, {
   "key": nextYear,
   "load": false
           }],
 
    "desc": currentYear
};
 
//Создаем модель с именем yearModel
var oModelYear = new sap.ui.model.json.JSONModel();
 
//Добавим в модель выше созданный массив
oModelYear.setData(year);
 
//установим модель с именем yearModel
this.getOwnerComponent().setModel(oModelYear, "yearModel");

Посмотрим что представляет из себя наша модель:
json model

  • Key — год.
  • load — флаг. Был ли загружен (выбран) когда-то уже данный год или нет.
  • В desc храниться выбранный год.

На этом подготовка закончена! Перейдем к манипуляциям с моделью!

Получить значение из модели (getProperty).

Если необходимо получить значение из модели:

1
2
3
4
5
6
7
8
//Получаем компонент
var oComp = this.getOwnerComponent ? this.getOwnerComponent() : this;
 
//Получаем модель
var oModel = oComp.getModel("yearModel");
 
//Получаем значение desc из данной модели (getProperty)
var oSelYear = oModel.getProperty("/desc");

Записать значение в модель (setProperty).

При необходимости записать данные в модель

1
2
3
4
5
//получили модель
var oModelYearSel = this.getOwnerComponent ? this.getOwnerComponent().getModel("yearModel") : this.getModel("yearModel");
 
//установили значение desc = currentYear, currentYear предварительно сделали строкой
oModelYearSel.setProperty( "/desc", currentYear.toString() );

Работа с массивом.

Хорошо, пробежимся по массиву items:

1
2
3
4
5
6
7
8
9
var model = that.getOwnerComponent() ? that.getOwnerComponent().getModel("yearModel") : that.getModel("yearModel");
var modelData = model.getProperty("/items");
 
//проверяем, является ли modelData массивом, если да то выполняется цикл
if (modelData instanceof Array) {
        modelData.forEach( function(oValue, i) {
          // обращаемся к элементам как oValue.key, oValue.load
  });
}

Конструкция выше плохая :), почему?

1) Возникают проблемы с областью видимости. Внутри function(oValue, i) вы не сможете использовать переменные, которые объявили в данном методе, в котором у вас используется данный цикл.

2) forEach медленный!
В IE 11 forEach работает на 75% медленней, нежели чем простой for! (смотрим тут https://jsperf.com/fast-array-foreach)
foreach vs for

заменим обычным циклом for:

1
2
3
4
5
6
7
8
9
var model = that.getOwnerComponent() ? that.getOwnerComponent().getModel("yearModel") : that.getModel("yearModel");
var modelData = model.getProperty("/items");
 
//проверяем, является ли modelData массивом, если да то выполняется цикл
if (modelData instanceof Array) {
    for (var i = 0; i < modelData.length; i++) {
       // обращаемся к элементам как modelData[i].key, modelData[i].load
    }
}

А можем обратиться напрямую к определенному элементу без циклов:

1
2
3
4
var model = that.getOwnerComponent() ? that.getOwnerComponent().getModel("yearModel") : that.getModel("yearModel");
var modelData = model.getProperty("/items");
 
    // обращаемся ко второму элементу как modelData[1], modelData[1].key итп

Если вложенность большая, то используем следующим образом:

1
var modelData = model.getProperty("/items/item1/item2");

так же можно получить доступ и к элементу массива (например, первому (нулевой элемент) ):

1
var modelData = model.getProperty("/items/item1/item2/0");