在控制器的 onInit 中读取 OData 上下文

Posted

技术标签:

【中文标题】在控制器的 onInit 中读取 OData 上下文【英文标题】:Reading OData contexts in onInit of controller 【发布时间】:2017-07-26 08:28:08 【问题描述】:

我尝试从 OData 源准备数据,以便在我的 fiori 应用程序的条形图中显示它。为此,我在 manifest.json 中设置了 OData 模型。带有列表的测试,只需使用

items="path : 'modelname>/dataset'

工作正常并显示内容。

为了为图表 (VizFrame) 准备数据,我在视图 (mvc:XMLView) 的控制器中使用了 onInit() 函数。数据准备与question 中讨论的类似。

首先我获得了ODataModel:

var oODataModel = this.getOwnerComponent().getModel("modelname");

接下来我进行绑定:

var oBindings = oODataModel.bindList("/dataset");

不幸的是,oBindings().getContexts() 数组始终为空,oBindings.getLength() 也为零。因此,VizFrame 仅显示“无数据”。

可能是onInit()函数期间数据模型没有完全加载,还是我对数据的访问方式有误解?

提前致谢

更新 我通过使用从将数据显示为列表的视图中自动创建的绑定暂时解决了这个问题。我从绑定getView().byId("myList").getBindings("items") 中获取“dataReceived”事件并在那里进行计算。图的模型(因为它用于不同的视图)在 Component.js 中创建,并在 Core sap.ui.getCore().setModel("graphModel") 中注册。 我认为这个解决方案很脏,因为图形数据依赖于来自不同视图的列表数据,这会导致问题,例如当您使用不断增长的列表时(因为绑定中的数据得到更新并且从 odata 模型中选择了不同的范围)。 有什么建议,我如何在不依赖不同列表的情况下获取 odata 模型条目?

【问题讨论】:

【参考方案1】:

下图概述了您的 UI5 应用程序的生命周期。

重要的是用红色圆圈突出显示的步骤。基本上,在您的onInit 中,您无法通过this.getView().getModel() 完全访问您的模型。

这可能就是您尝试使用this.getOwnerComponent().getModel() 的原因。这使您可以访问模型,但它尚未绑定到视图,因此您不会获得任何上下文。

类似地,metadataLoaded() 返回一个过早完成的 Promise:在加载元数据之后,可能在任何视图绑定完成之前。

我通常做的是

使用onBeforeRendering

这是在onInit 之后立即调用的生命周期挂钩。视图及其模型存在,但尚未向用户显示。很有可能用你的模型做一些事情。

使用onRouteMatched

这并不是一个真正的生命周期钩子,而是一个可以绑定到应用程序的路由器对象的事件处理程序。由于您在 onInit 中定义了事件处理程序,它将稍后调用(但不会太晚),然后您可以做您想要的事情。这显然只有在您设置了路由时才有效。

【讨论】:

这篇文章回答的比原来的问题更多。很有价值的图,谢谢。我将评估移到 onBeforeRendering 函数中。但现在我想,我的问题是绑定本身。我在视图本身没有绑定。例如。在一个列表中,我有类似items="path:'...' 的东西,它会自动创建绑定。所以也许,问题实际上是:如何手动将这样的绑定添加到视图中? 请告诉我,如果我理解图表正确。 * 在控制器的初始化函数中,我将 listBinding 添加到数据模型中(这似乎可行,因为可以在显示模型的调试输出中找到绑定)。 * 在“评估绑定”和“数据检索”中,我的绑定应该由数据填充,还是? * 当视图更新时(调用 onBeforeRendering 函数?),我应该可以访问绑定中的数据,例如获取上下文?列表自动创建的绑定,数据可用,但手动创建的没有。为什么? 我不完全确定你为什么需要这些上下文。你能详细说明一下吗? 这个想法是,我遍历数据,计算元素并创建新数据,其中包含以下内容:在 X 天,在下午 1 点到 1:59 之间的时间,是 Y 元素的状态1. 可能比之前问的question 嗯,好的。如果我想获取数据,我总是使用read 方法。 openui5.hana.ondemand.com/#docs/api/symbols/… 您可以提供类似于绑定的过滤器和分类器,但这似乎是一种更直接的方法。成功函数包含您的数据作为一个简单的 JS 对象。【参考方案2】:

您必须等到模型元数据加载完毕。试试这个:

onInit: function() 
    var oBindings;
    var oODataModel = this.getComponent().getModel("modelname");
    oODataModel.metadataLoaded().then(function() 
        oBindings = oODataModel.bindList("/dataset");
    .bind(this));
,

【讨论】:

谢谢,我认为这指向了正确的方向。但是为了理解:什么时候执行“then”后面的函数?就我而言,metadataLoaded() 函数返回[[PromiseStatus]]:"resolved",并且设置了oBindings? metadataLoaded()函数和attachMetadataLoaded()类似吗? 我不能确切地告诉你。大概吧。试试 attachMetadataLoaded :-) 我现在有oODataModel.attachMetadataLoaded(handler);,它被调用了。在 handler 的函数中,oODataModel 具有属性 oMetadata->bLoaded: true,还有一个 oData 对象,其中包含我的 odata 的前 20 个条目。但是,getContexts() 仍然是空的。 图表视图中是否不可能发生事件“dataReceived”?您想要有 2 个视图,列表和图表?【参考方案3】:

可能是在 onInit() 期间数据模型没有完全加载 函数,还是我误解了访问数据的方式?

您可以在执行列表绑定之前通过控制台记录您的模型是否已完全加载

console.log(oODataModel);
var oBindings = oODataModel.bindList("/dataset");

如果您的模型不包含数据,那就是问题所在。

【讨论】:

控制台显示模型。例如。 mContexts 下面是来自 oData 的前 20 个条目的列表,aBindings 包含一个包含 81 个对象的数组(每个对象都有属性 sPath="/dataset")。【参考方案4】:

我的基本误解是强制使用绑定。这似乎只适用于组织数据处理的 UI 元素。我换了

oODataModel.read("/dataset", success: function(oEvent) 
    // do all my calculations on the oEvent.results array
    // write result into graphModel
    
);

整个计算都在附加到 graphModel 的 requestSent 事件的函数中,该函数在视图/控制器的 onBeforeRendering 部分中设置为 VizFrame 的模型。

【讨论】:

以上是关于在控制器的 onInit 中读取 OData 上下文的主要内容,如果未能解决你的问题,请参考以下文章

使用 apicontroller vs odata EntitySetController [关闭]

如何在 OData 请求中添加 Context Guid

如何在 C# 操作中读取 OData URL 参数值?

SAPUI5 何时将初始过滤器绑定到控件

组件 $onInit() 在控制器中看不到变量 - angularjs 1.6.x

SAPUI5 列表绑定与 XML 视图中的过滤数据