UI5:从XML视图多次调用格式化程序或过早

时间:2019-11-11 09:34:56

标签: data-binding sapui5 formatter

我正在使用OpenUI5。使用formatter.js,我在视图中格式化了一些文本。

但是我的格式化程序被调用了3次:

  1. 当我将模型绑定到面板控件时:oPanel.setModel(oModel, "data"); sBirthdaysFormat均为undefined

  2. onInit()完成并呈现视图之后: sBirthday已正确定价,sFormatundefined

  3. 再次:sBirthdaysFormat均正确地得到了估价。

为什么会这样?正确吗?
该应用出现错误,因为格式化程序中的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 个答案:

答案 0 :(得分:2)

  • 仅在数据请求完成时将模型设置为视图:

    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(true)调用,该操作在绑定初始化时发生;请参见下文),并且此后未检测到进一步的更改。

  • (可选)使格式化程序更具防御性。像这样:

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

  

为什么会这样?

  1. 视图被实例化。
  2. 控制器的
  3. onInit被调用。在此,请求文件model/data.json(模型为空)。
  4. 将视图添加到UI后,UI5传播现有父对象 建模到视图。
  5. 初始化视图中的绑定,并在每个视图中触发checkUpdate(/*forceUpdate*/true) src
  6. 由于激活了forceUpdate标志,因此触发了change事件,即使没有任何更改,它也会强制触发格式化程序:
    [undefined, undefined][undefined, undefined]。 -第一个格式化程序调用
  7. 获取model/data.json现已完成。现在,该模型需要再次checkUpdate
  8. [undefined, undefined][value1, undefined]→检测到更改→第二次格式化程序调用
  9. [value1, undefined][value1, value2]→检测到更改→第三次格式化程序调用

答案 1 :(得分:0)

现在,考虑到您试图将静态JSON文件加载到项目中,最好最大化manifest.json的使用率。

这样,您可以确定在进行任何绑定之前,数据已经在模型中加载并可用。

您可以通过将JSON文件添加为 sap.app

下的数据源来实现此目的。

manifest.json

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

现在,只需在 sap.ui5 下将名为dataSource的{​​{1}}添加为data之一即可。

models

有了这个,您不需要再打电话了

"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.jsonoView一开始就已经可见。

这样,格式化程序是否被多次调用无关紧要,因为它从一开始就已经有可用的数据。