无法从sapUI5

时间:2015-12-08 19:31:39

标签: model-view-controller sapui5

跟进相关问题 here

无论出于何种原因,当我通过sap.ui.getCore()。setModel()设置时,我无法在我的xml视图中访问我的模型。如果我在this.getView()上设置它,我完全没有问题。

我的观点XML

<mvc:View controllerName="ca.toronto.rcsmls.webapp.controller.Login"
xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:l="sap.ui.layout">

<Page title="{i18n>loginPageTitle}">
    <content>

        <Panel id="loginPanel" busyIndicatorDelay="0"
            headerText="{i18n>loginPanelTitle}" class="sapUiResponsiveMargin loginPanel"
            width="auto">
            <l:VerticalLayout width="100%">


                <Input type="Text" placeholder="{i18n>loginUidHolder}" value="{/mlsUser/uid}" />

                <Input type="Password" placeholder="{app>/Password}"
                    value="{/mlsUser/password}" />

                <Button text="{i18n>loginButtonText}" press="doLogin"
                    class="sapUiSmallMarginEnd customBold" width="100%" />


            </l:VerticalLayout>
        </Panel>

    </content>
</Page></mvc:View>

我的控制器JS包含这个用于setModel()

 onInit : function() {
        sap.ui.getCore().setModel(new sap.ui.model.json.JSONModel("webapp/controller/app.json"), "app");
    }

同样,如果我将模型设置为this.getView()。setModel()而不是getCore(),XML和控制器可以很好地协同工作。我还在我的index.html中添加了 data-sap-ui-xx-bindingSyntax =“complex”,但这似乎没有什么区别。任何帮助将不胜感激。

已修改以包含更多信息

我的Component.js

sap.ui.define([
   "sap/ui/core/UIComponent",
   "sap/ui/model/json/JSONModel",
], function (UIComponent, JSONModel) {
   "use strict";
   return UIComponent.extend("ca.toronto.rcsmls.webapp.Component", {
      metadata : {
          manifest: "json"
      },
      init : function () {
         // call the init function of the parent
         UIComponent.prototype.init.apply(this, arguments);
         // set data model
         var oData = {
            mlsUser : {
               uid : "",
               password : "",
            }
         };
         var oModel = new JSONModel(oData);
         this.setModel(oModel);

         // create the views based on the url/hash
         this.getRouter().initialize();
      }
   });
});

我的manifest.json

{
    "_version": "1.1.0",
    "sap.app": 
    {
        "_version": "1.1.0",
        "id": "ca.toronto.rcsmls",
        "type": "application",
        "i18n": "i18n/i18n.properties",
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "applicationVersion": 
        {
            "version": "1.0.0"
        },

        "ach": "CA-UI5-DOC"
    },

    "sap.ui": 
    {
        "_version": "1.1.0",
        "technology": "UI5",
        "deviceTypes": 
        {
            "desktop": true,
            "tablet": true,
            "phone": true
        },

        "supportedThemes": 
        [
            "sap_bluecrystal"
        ]
    },

    "sap.ui5": 
    {
        "_version": "1.1.0",
        "rootView": "ca.toronto.rcsmls.webapp.view.App",
        "dependencies": 
        {
            "minUI5Version": "1.30",
            "libs": 
            {
                "sap.m": 
                {

                }
            }
        },

        "config": 
        {
            "authenticationService": "http://172.21.226.138:9080/RcsMlsSvc/jaxrs/user/authenticate/",
            "assignedWorkService": "http://172.21.226.138:9080/RcsMlsSvc/jaxrs/mls/searchAssignedWork"
        },

        "models": 
        {
            "i18n": 
            {
                "type": "sap.ui.model.resource.ResourceModel",
                "settings": 
                {
                    "bundleName": "ca.toronto.rcsmls.webapp.i18n.i18n"
                }
            }
        },

        "routing": 
        {
            "config": 
            {
                "routerClass": "sap.m.routing.Router",
                "viewType": "XML",
                "viewPath": "ca.toronto.rcsmls.webapp.view",
                "controlId": "root",
                "controlAggregation": "pages"
            },

            "routes": 
            [
                {
                    "pattern": "",
                    "name": "login",
                    "target": "login"
                },
                {
                    "pattern": "work",
                    "name": "work",
                    "target": "work"
                }
            ],

            "targets": {
                "login": {
                    "viewName": "Login"
                },
                "work": {
                    "viewName": "Work"
                }
            }
        },

        "resources": 
        {
            "css": 
            [
                {
                    "uri": "css/style.css"
                }
            ]
        }
    }
}

模型app.json

{
    "BaseURL": "https://smp-pNNNNNNtrial.hanatrial.ondemand.com",
    "ES1Root": "https://sapes1.sapdevcenter.com",
    "AppName": "qmacro.myfirst",
    "Username": "yourusername",
    "Password": "yourpassword"
}

我找到了核心绑定工作here的示例。这是一个更简单的应用程序。我还在试图弄清楚这个项目与我的差异

4 个答案:

答案 0 :(得分:3)

我通过Github

上的类似问题了解了这个问题

默认情况下,UI5组件不会从其环境(放置它们的ComponentContainer)继承模型和绑定上下文。这样做是为了隔离。

您可以通过为容器设置属性propagateModel:true来更改默认行为:

new sap.ui.core.ComponentContainer({
  name: "ca.toronto.rcsmls.webapp.Component",
  propagateModel: true
}).placeAt("content");

propagateModel的文档可以在API reference以及UI5 developer guide中找到(后一页中的相应段落最近才添加,它不是提出问题时可以使用)。

但是当在组件的范围内创建模型并且应该在组件内部使用时,则不需要将其添加到Core中。只需将其分配给组件即可在该组件内的视图之间共享:

从视图控制器中的某个方法分配它

onInit : function() {
    this.getOwnerComponent().setModel(
        new sap.ui.model.json.JSONModel(
            "webapp/controller/app.json"), "app");
}

或在初始化Component.js本身

期间
init : function() {
    // create and set model to make it available to all views
    this.setModel(
        new sap.ui.model.json.JSONModel(
            "webapp/controller/app.json"), "app");

    // never forget to call init of the base class
    UIComponent.init.apply(this, arguments);
}

最现代的方法是在manifest.json中配置模型,并让框架实例化赋值。有关示例,请参阅Walkthrough Tutorial - Step 10: Descriptor for Applications

使用这些方法中的任何一种,甚至不需要在另一个视图中读取和设置模型,只要该视图是组件的后代(由createContent返回的控制树的一部分)。

答案 1 :(得分:1)

我经历过同样的行为。 如果我创建一个简单的单文件应用程序,没有任何复杂的UI元素,基于核心的绑定就像魅力一样。

如果我创建一个复杂的容器,就像带有shell的App一样,这种绑定将不再起作用。看起来这些容器从视图中隐藏了全局模型。

作为一种解决方法,我使用了以下代码段:

this.getView().setModel(sap.ui.getCore().getModel(modelName), "modelName");

甚至可以将模型直接绑定到您要使用的控件上。

如果您必须在多个视图/控件中使用全局模型,它们都不是最佳解决方案,但这对我有用。

答案 2 :(得分:0)

我上面的视图只有密码字段的占位符正在使用您的应用模型。如果此占位符未正确填充,那么我猜想无法加载json文件,或者内容与您在视图中用于密码字段的占位符属性的绑定路径不匹配。要了解更多信息,请发布您的json文件的内容。看起来应该是这样的:

{ "Password" : "Enter your password", ... }

因此,根据视图中的绑定,数据对象的根级别必须有“Password”属性。

下面你会找到一个可以帮助你的运行示例。正如您所看到的,它就像魅力一样,因此您可以轻松地将命名模型放在Core上并在视图中引用它。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>SAPUI5 single file template | nabisoft</title>
        <script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
            id="sap-ui-bootstrap"
            data-sap-ui-theme="sap_bluecrystal"
            data-sap-ui-libs="sap.m"
            data-sap-ui-bindingSyntax="complex"
            data-sap-ui-compatVersion="edge"
            data-sap-ui-preload="async"></script>
            <!-- use "sync" or change the code below if you have issues -->

        <!-- XMLView -->
        <script id="myXmlView" type="ui5/xmlview">
            <mvc:View
                controllerName="MyController"
                xmlns="sap.m"
                xmlns:core="sap.ui.core"
                xmlns:l="sap.ui.layout"
                xmlns:mvc="sap.ui.core.mvc">
                <App>
                    <Page title="My Page Title">
                        <content>
                            <Panel id="loginPanel" busyIndicatorDelay="0"
                                headerText="My Login Panel Title" class="sapUiResponsiveMargin loginPanel"
                                width="auto">
                                <l:VerticalLayout width="100%">

                                    <Input type="Text" placeholder="{Enter User ID}" value="{/mlsUser/uid}" />

                                    <Input type="Password" placeholder="{app>/Password}" value="{/mlsUser/password}" />

                                    <Button text="{Login}" press="doLogin" class="sapUiSmallMarginEnd customBold" width="100%" />

                                </l:VerticalLayout>
                            </Panel>
                        </content>
                    </Page>
                </App>
            </mvc:View>
        </script>

        <script>
            sap.ui.getCore().attachInit(function () {
                "use strict";

                //### Controller ###
                sap.ui.controller("MyController", {
                    onInit : function () {
                        var oData, oModel;

                        // 1. app model is only used for the placeholder field in the view
                        oData = {
                            Password : "Enter your password"
                        };
                        oModel = new sap.ui.model.json.JSONModel(oData);
                        sap.ui.getCore().setModel(oModel, "app");

                        // 2. default model is used in the view as well
                        oData = {
                            mlsUser : {},
                            Login : "Login now"
                        };
                        oModel = new sap.ui.model.json.JSONModel(oData);
                        sap.ui.getCore().setModel(oModel);

                        // 3. we need this because of the relative binding
                        //    of the text property of the login button
                        this.getView().bindElement("/");

                    }
                });

                //### THE APP: place the XMLView somewhere into DOM ###
                sap.ui.xmlview({
                    viewContent : jQuery("#myXmlView").html()
                }).placeAt("content");

            });
        </script>

    </head>

    <body class="sapUiBody">
        <div id="content"></div>
    </body>
</html>

在这个帖子中,有些人提到“sap.ui.getCore()适用于小东西,但无论出于何种原因都不适用于更复杂的应用程序”。

@Marc还发布了right link to the API docs,您可以在其中找到以下内容:

  

ManagedObject仅在它是a时从Core继承模型   UIArea的后裔

当然,您必须知道这对于编写符合您预期效果的代码意味着什么。这是一个小例子,告诉你如果你有一个小的“误解”会发生什么(见下文)。

下面的代码创建了两个sap.m.Text实例,并将它们的文本属性绑定到JSONModel,JSONModel可直接作为Core上的命名模型“core”(使用sap.ui.getCore()检索)。有2个按钮,每个按钮对应一个sap.m.Text实例。在按钮的相应按下处理程序中,我只显示相应sap.m.Text实例的text属性。如您所见,两个sap.m.Text实例都绑定到JSONModel中的相同属性。但是,只有第二个sap.m.Text被添加到DOM中。

现在有趣的部分,可能与此线程的混乱有关: 只有第二个sap.m.Text控件的text属性包含来自JSONModel的预期文本“Hello World”。第一个sap.m.Text控件的text属性没有模型中的“Hello World”值!这是SAPUI5的预期行为,并且已记录在案!所以我想如果你在自己的“复杂”应用程序中遇到类似的问题,那么你很可能很难找到与这种“预期”行为相关的错误。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>SAPUI5 single file template | nabisoft</title>
        <script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
            id="sap-ui-bootstrap"
            data-sap-ui-theme="sap_bluecrystal"
            data-sap-ui-libs="sap.m"
            data-sap-ui-bindingSyntax="complex"
            data-sap-ui-compatVersion="edge"
            data-sap-ui-preload="async"></script>
            <!-- use "sync" or change the code below if you have issues -->

        <script>
            sap.ui.getCore().attachInit(function () {

                sap.ui.define([
                    "sap/m/Text",
                    "sap/m/Button",
                    "sap/ui/model/json/JSONModel"
                ], function (Text, Button, JSONModel) {
                    "use strict";

                    var oModel = new JSONModel({
                        hello : "Hello World"
                    });
                    sap.ui.getCore().setModel(oModel, "core");

                    // not in DOM
                    var oText1 = new Text({
                        text : "{core>/hello}"
                    });
                    //oText1.placeAt("text1");      // uncomment this to enable the binding

                    // add to DOM
                    var oText2 = new Text({
                        text : "{core>/hello}"
                    });
                    oText2.placeAt("text2");

                    // action buttons to display text property of text controls
                    new Button({
                        text : "show oText1",
                        press : function(){
                            alert("oText1.getText() = " + oText1.getText());
                        }
                    }).placeAt("btn1");

                    new Button({
                        text : "show oText2",
                        press : function(){
                            alert("oText2.getText() = " + oText2.getText());
                        }
                    }).placeAt("btn2");

                });
            });
        </script>

    </head>

    <body class="sapUiBody">
        <div id="text1"></div>
        <div id="text2"></div>
        <span id="btn1"></span>
        <span id="btn2"></span>
    </body>
</html>

答案 3 :(得分:-1)

sap.ui.getCore()this.getView()返回不同的对象,我认为这显然不起作用。

你试图从另一个对象(核心)获取一个对象(模型),尽管所需的模型绑定到另一个对象(视图)

它就像我有两个彩色的盒子(一个红色,一个蓝色),我试图从蓝色框中获得红色

这是一个类似的问题,但是这个问题的原因取决于UI5框架中视图的id处理: https://scn.sap.com/thread/3551589

您可以看到核心和视图不会返回相同的对象

还要检查openui5网站上的数据绑定部分:https://openui5beta.hana.ondemand.com/#docs/guide/e5310932a71f42daa41f3a6143efca9c.html

在components.js中创建模型:

var oModel= new sap.ui.model.json.JSONModel;
oModel.loadData("webapp/controller/app.json");
this.setModel(oModel, "app");

获取型号: 这将创建对在Components.js

中创建的模型的引用
var oModel= this.getView().getModel("app");

请参阅模型&#34; {modelName(app)&gt; desiredProperty}&#34;

<Input type="Password" placeholder="{app>Password}"
                    value="{app>mlsUser/password}" />
你可以发布你的json内容吗?

希望这是有帮助的