UI5:格式化程序从 XML 视图调用多次或过早
UI5: Formatter called multiple times or too soon from an XML view
我正在使用 OpenUI5。使用 formatter.js
,我在视图中格式化了一些文本。
但是我的格式化程序被调用了 3 次:
当我将模型绑定到面板控件时:oPanel.setModel(oModel, "data");
sBirthday
和 sFormat
都是 undefined
.
onInit()
完成并渲染视图后:
sBirthday
正确定值,sFormat
是 undefined
再次强调:sBirthday
和 sFormat
均已正确定价。
为什么会这样?正确吗?
应用出现错误,因为格式化程序中的 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"
}
}
}
仅在数据请求完成时将模型设置为视图:
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;
}
Why does this happen?
- 视图被实例化。
控制器的 onInit
被调用。此处,请求文件 model/data.json
(模型为空)。
- 将视图添加到 UI 后,UI5 传播现有父视图
模型到视图。
- 视图内的绑定被初始化,触发
checkUpdate(/*forceUpdate*/<strong>true</strong>)
src 在每一个中。
- 由于
forceUpdate
标志被激活,change
事件被触发,即使根本没有任何变化也会强制触发格式化程序:
[undefined, undefined]
→ [undefined, undefined]
。 - 第一次格式化程序调用
- 获取
model/data.json
现已完成。现在模型需要再次checkUpdate
。
[undefined, undefined]
→ [value1, undefined]
→ 检测到更改 → 2nd 格式化程序调用
[value1, undefined]
→ [value1, value2]
→ 检测到更改 → 3rd 格式化程序调用
现在,鉴于您正在尝试将静态 JSON 文件加载到您的项目中,最好最大限度地利用 manifest.json
。
这样,您就可以确定在任何绑定之前数据已经加载并在模型中可用。
您可以通过将 JSON 文件作为 数据源 添加到 sap.app[=21 下来实现此目的=]
manifest.json
"sap.app": {
"id": "com.sample.app",
"type": "application",
"dataSources": {
"data": {
"type": "JSON",
"uri": "model/data.json"
}
}
}
现在,只需将这个名为 data
的 dataSource
添加为 sap.ui5 下的 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");
..因为我们在 manifest.json
中添加的 data model
从一开始就已经对 oView
和 oPanel
可见。
这样,格式化程序是否被多次调用并不重要,因为它从一开始就已经拥有可用的数据。
我正在使用 OpenUI5。使用 formatter.js
,我在视图中格式化了一些文本。
但是我的格式化程序被调用了 3 次:
当我将模型绑定到面板控件时:
oPanel.setModel(oModel, "data");
sBirthday
和sFormat
都是undefined
.onInit()
完成并渲染视图后:sBirthday
正确定值,sFormat
是undefined
再次强调:
sBirthday
和sFormat
均已正确定价。
为什么会这样?正确吗?
应用出现错误,因为格式化程序中的 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"
}
}
}
仅在数据请求完成时将模型设置为视图:
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; }
Why does this happen?
- 视图被实例化。 控制器的
onInit
被调用。此处,请求文件model/data.json
(模型为空)。- 将视图添加到 UI 后,UI5 传播现有父视图 模型到视图。
- 视图内的绑定被初始化,触发
checkUpdate(/*forceUpdate*/<strong>true</strong>)
src 在每一个中。 - 由于
forceUpdate
标志被激活,change
事件被触发,即使根本没有任何变化也会强制触发格式化程序:
[undefined, undefined]
→[undefined, undefined]
。 - 第一次格式化程序调用 - 获取
model/data.json
现已完成。现在模型需要再次checkUpdate
。 [undefined, undefined]
→[value1, undefined]
→ 检测到更改 → 2nd 格式化程序调用[value1, undefined]
→[value1, value2]
→ 检测到更改 → 3rd 格式化程序调用
现在,鉴于您正在尝试将静态 JSON 文件加载到您的项目中,最好最大限度地利用 manifest.json
。
这样,您就可以确定在任何绑定之前数据已经加载并在模型中可用。
您可以通过将 JSON 文件作为 数据源 添加到 sap.app[=21 下来实现此目的=]
manifest.json
"sap.app": {
"id": "com.sample.app",
"type": "application",
"dataSources": {
"data": {
"type": "JSON",
"uri": "model/data.json"
}
}
}
现在,只需将这个名为 data
的 dataSource
添加为 sap.ui5 下的 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");
..因为我们在 manifest.json
中添加的 data model
从一开始就已经对 oView
和 oPanel
可见。
这样,格式化程序是否被多次调用并不重要,因为它从一开始就已经拥有可用的数据。