UI5: Formatter вызывается несколько раз или слишком рано из представления XML - PullRequest
1 голос
/ 11 ноября 2019

Я использую OpenUI5. Используя formatter.js, я отформатировал некоторый текст в моем виде.

Но мой форматер вызывается 3 раза:

  1. Когда я связываю модель с панелью управления:oPanel.setModel(oModel, "data"); и sBirthday, и sFormat являются undefined.

  2. После того, как onInit() завершен и представление отображается: sBirthday оценивается правильно и sFormatundefined

  3. Опять же: sBirthday и sFormat ara правильно оценены.

Почему это происходит? Это правильно?
Приложение получает ошибку, потому что ageDescription() в форматере не может управлять undefined значениями.

formatter.js

sap.ui.define([], function () {
  "use strict";

  return {
    ageDescription : function (sBirthday, sFormat) {
      do.something();
      var sFromMyBd = moment(sBirthday, sFormat).fromNow();
      do.something();
      return sAge;
    }
  }
});

main.view.xml

<mvc:View
  controllerName="controller.main"
  xmlns="sap.m"
  xmlns:mvc="sap.ui.core.mvc">
  <Panel id="user-panel-id">
    <Input id="name-input-id" enabled="false" value="{data>/user/name}" />
    <Label text="{i18n>age}: " class="sapUiSmallMargin"/>
    <Label text="{
      parts: [
        {path: 'data>/user/birthday'},
        {path: 'data>/user/dateFormat'}
      ],
      formatter: '.formatter.ageDescription' }"/>
  </Panel>
</mvc:View>

Main.controller.js

sap.ui.define([
  "sap/ui/core/mvc/Controller",
  "sap/ui/model/json/JSONModel",
  "model/formatter"
], function (Controller, JSONModel, formatter) {
  "use strict";

  return Controller.extend("controller.main", {
    formatter: formatter,
    onInit: function () {
      var oModel = new JSONModel();
      var oView = this.getView();
      oModel.loadData("model/data.json");
      var oPanel = oView.byId("user-panel-id");
      oPanel.setModel(oModel,"data");
      do.something();
    },
  });
});

data.json

{
  "user": {
    "name": "Frank",
    "surname": "Jhonson",
    "birthday": "23/03/1988",
    "dateFormat": "DD/MM/YYYY",
    "enabled": true,
    "address": {
      "street": "Minnesota street",
      "city": "San Francisco",
      "zip": "94112",
      "country": "California"
    }
  }
}

Ответы [ 2 ]

2 голосов
/ 11 ноября 2019
  • Установите модель для вида только после завершения запроса данных:

    onInit: function() {
      const dataUri = sap.ui.require.toUri("<myNamespace>/model/data.json");
      const model = new JSONModel(dataUri);
      model.attachEventOnce("requestCompleted", function() {
        this.getView().setModel(model);
      }, this);
      // ...
    },
    

    Это гарантирует, что форматер вызывается только один раз (вызывается checkUpdate(<strong>true</strong>), что происходит приинициализация привязки (см. ниже), и никаких дальнейших изменений не обнаружено впоследствии.

  • Дополнительно (или альтернативно), сделайте форматер более защищенным. Что-то вроде:

    function(value1, value2) {
      let result = "";
      if (value1 && value2) {
        // format accordingly ...
      }
      return result;
    }
    

Почему это происходит?

  1. Представление создается.
  2. onInit контроллера вызывается. Здесь запрашивается файл model/data.json (модель пуста).
  3. После добавления представления в пользовательский интерфейс UI5 распространяет существующие родительские модели в представление.
  4. Привязки в представлении инициализируютсясрабатывание checkUpdate(/*forceUpdate*/<strong>true</strong>) src в каждом из них.
  5. Из-за активированного флага forceUpdate происходит событие change, которое принудительно вызываетсредства форматирования, даже если изменений не было вообще:
    [undefined, undefined][undefined, undefined]. - 1-й вызов форматера
  6. Получение model/data.json завершено. Теперь модели нужно снова checkUpdate.
  7. [undefined, undefined][value1, undefined] → обнаружено изменение → 2nd вызов форматирования
  8. [value1, undefined][value1, value2] →Обнаружено изменение → 3-й вызов форматтера
0 голосов
/ 12 ноября 2019

Теперь, учитывая, что вы пытаетесь загрузить статический файл JSON в свой проект, лучше максимально использовать manifest.json.

Таким образом, вы уверены, что данные уже загружены и доступны в модели до какой-либо привязки.

Это достигается путем добавления файла JSON в качестве источника данных под sap.app

manifest.json

"sap.app": {
    "id": "com.sample.app",
    "type": "application",
    "dataSources": {
        "data": {
            "type": "JSON",
            "uri": "model/data.json"
        }
    }
}

Теперь просто добавьте это dataSourceВызывается data как один из models в sap.ui5 .

"sap.ui5": {
    "rootView": {
        "viewName": "com.sample.app.view.App",
        "type": "XML"
    },
    "models": {
        "i18n": {
            "type": "sap.ui.model.resource.ResourceModel",
            "settings": {
                "bundleName": "com.app.sample.i18n.i18n"
            }
        },
        "data": {
            "type": "sap.ui.model.json.JSONModel",
            "dataSource": "data"
        }
    }
}

При этом вам больше не нужно вызывать это :

var oModel = new JSONModel();
var oView = this.getView();
oModel.loadData("model/data.json");
var oPanel = oView.byId("user-panel-id");
oPanel.setModel(oModel,"data"); 

.. поскольку data model, который мы добавили в manifest.json, уже видны oView и oPanel с самого начала.

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

...