2015-12-08 2 views
2

Последующие меры смежный вопрос hereНевозможно получить доступ к модели из ядра в sapUI5

По какой-то причине я не могу получить доступ к моей модели, на мой взгляд XML, когда он установлен через sap.ui.getCore(). SetModel(). Если я установлю его на 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 и контроллер работают отлично. Я также добавил data-sap-ui-xx-bindingSyntax = "complex" к моему index.html, но это, похоже, не изменило ситуацию. Любая помощь будет оценена по достоинству.

Edited включить больше информации

Мои 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. Это гораздо более простое приложение. Я все еще пытаюсь выяснить, каковы различия между этим проектом и мином.

+0

Я не могу сказать вам, почему он не работает (у нас есть та же проблема), но я могу рассказать вам об обходном пути: мы настраиваем большинство моделей в нашем 'manifest.json', а остальные в' Component.js'. Чтобы сделать их в глобальном 'Component.js', выполните' this.setModel (oModel, "app") 'после их инициализации. См. Эту страницу, например: https://help.sap.com/saphelp_uiaddon10/helpdata/en/32/5b8edafcfa4c9c8fbd42455a60e379/content.htm – Marc

+0

@ Маркус, не возражаете ли вы опубликовать пример, чтобы проиллюстрировать ваш случай, когда он не работает? У меня никогда не было проблем с этим, см. Также мой пример кода в моем ответе ниже. Он должен работать нормально, иначе я думаю, что это ошибка в UI5 или в собственном коде. – Nabi

+0

@Nabi as @ nistv4n указал, что это 'sap.ui.getCore()' вещь работает с небольшим материалом, но по какой-либо причине не в более сложных приложениях. Я попытаюсь создать более сложный пример, но для этого потребуется некоторое время с момента его создания. – Marc

ответ

2

я был сделан в курсе этого вопроса на аналогичный вопрос о 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 (соответствующего пункта в последнем страница была добавлена ​​только недавно, она не была доступна, когда вы подняли свой вопрос).

Но когда модель создается в рамках компонента и должна использоваться внутри компонента, тогда нет необходимости добавлять ее в ядро. Просто назначить его компоненту, чтобы поделиться между видами внутри этого компонента:

Назначают его либо из какого-то метода в контроллере представления

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); 
} 

Самый современный подход состоит в том, чтобы сконфигурировать модель в манифесте. Json и позволить фреймворку инстанцировать его назначение. См. Пример Walkthrough Tutorial - Step 10: Descriptor for Applications.

Использование любого из этих подходов не должно быть необходимости читать и устанавливать модель в другом представлении, если это представление является потомком компонента (часть дерева управления, возвращаемого createContent).

+0

Не могли бы вы прояснить _Но когда модель создана внутри компонента и используется внутри компонента [...] _? Я добавил код в Component.js, но, на мой взгляд, я до сих пор не могу получить доступ к нему с помощью «{app>/property}» '. (_this.getOwnerComponent() не является функцией_) – modiX

+1

Фрагмент кода предназначался для использования в контроллере представления, который хочет разделить модель с другими представлениями (контроллерами представлений). Если вы хотите создать модель в самой Component.js, она выглядит несколько иначе. Я обновил свой пост, чтобы уточнить разницу. – codeworrior

0

Я смотрю выше только заполнитель поля пароля, используя вашу модель приложения. Если этот заполнитель заполнен неправильно, я думаю, что json-файл не может быть загружен или содержимое не соответствует пути привязки, который вы используете в своем представлении для свойства placeholder поля пароля. Чтобы узнать больше, напишите также содержимое вашего json-файла. Это должно выглядеть как-то так:

{ "Password" : "Enter your 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 наследует модели из Ядра только тогда, когда это потомок UIArea

Конечно , вы должны знать, что это значит, чтобы написать код, который делает то, что вы ожидаете. Вот небольшой пример, который говорит вам, что может произойти, если у вас небольшое «недоразумение» (см. Ниже).

Код ниже создает два экземпляра sap.m.Text и связывает их текстовые свойства с JSONModel, который доступен как именованная модель «ядро» непосредственно на ядре (получена с помощью sap.ui.getCore()) , Есть 2 кнопки, по одному для каждого экземпляра sap.m.Text. В соответствующих обработчиках нажатия кнопок я просто отображаю свойство text соответствующего экземпляра sap.m.Text. Как вы можете видеть, оба экземпляра sap.m.Text привязаны к одному и тому же свойству в JSONModel. Однако в DOM добавляется только второй sap.m.Text.

Теперь интересная часть, которая может быть связана с путаницей этого потока: Только текстовое свойство второго элемента управления sap.m.Text содержит ожидаемый текст «Hello World» из JSONModel. Свойство text первого элемента управления sap.m.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>

+0

спасибо для подробного объяснения и примеров. Я не хотел, чтобы мой ответ затерялся в ответах, поэтому я также комментирую ваш пост. \t Я наткнулся на этот проект, где привязка ядра работает https://github.com/qmacro/w3u3_redonebasic/tree/xmlviews. Разница с моим проектом заключается в том, что я добавил маршрутизацию, используя это руководство https://openui5beta.hana.ondemand.com/#docs/guide/e5200ee755f344c8aef8efcbab3308fb.html. Кажется, что маршрутизация влияет на это поведение? – quikbeam

+0

@quikbeam Не могли бы вы опубликовать свой манифест.json, а также ваш файл Component.js? Я также доказал, что мой код должен работать. Если это не сработает, значит, что-то не так. Использование маршрутизации не должно быть проблемой вообще, если ваш код не делает «что-то особенное». – Nabi

1

я испытал такое же поведение. Если я создаю простое однофазное приложение, без каких-либо сложных элементов пользовательского интерфейса, привязка на основе работает как шарм.

Если я создаю сложный контейнер, например приложение с оболочкой, этот вид привязки больше не будет работать. Кажется, что эти контейнеры скрывают глобальную модель от представления.

В качестве обходного пути я использовал следующий фрагмент кода:

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

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

Ни одно из них не является лучшим решением, если вам нужно использовать глобальную модель в нескольких режимах просмотра/управления, но это работает на меня.

+1

Можете ли вы предложить полный пример, где он не работает для вас? Я считаю, что это ошибка, если она не работает !!! Я распространил свой ответ на рабочий пример, чтобы доказать, что использование именованной модели из Core абсолютно нормально. Никто не скрывает глобальную модель, если она не «скрыта» собственным кодом. – Nabi

-1

sap.ui.getCore() и this.getView() возврат не тот же объект Я думаю, что это понятно, почему это не работает.

Вы пытаетесь получить объект (модель) от другого объекта (ядро), хотя желаемая модель привязан к другому объекту (вид)

это как у меня есть две цветные коробки (один красный, один синий) и им пытаются получить красный цвет от синего цвета коробки

Вот аналогичный вопрос, но причина в этом, зависит от обработки ид взглядов в рамках UI5: https://scn.sap.com/thread/3551589

You может видеть ядро, а вид не возвращает sam e объект.

Также проверка данных раздел связывания на сайте 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"); 

Обратитесь к модели с "{ModelName (приложение)> desiredProperty}"

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

Вы могли бы разместить свой контент json?

Надежда это было полезно

Смежные вопросы