2

I have a homepage with two tiles which is working as expected. On clicking tile one, my control should navigate to "SearchProductPage".

I have the following files:

  • homepage.view.js
  • homepage.controller.js
  • SearchProductPage.view.js
  • SearchProductPage.controller.js

So when I click on the tile, I get the alert messages per code. But my code is not navigating to the SearchProductPage.view.js.

And when trying to access the router, it returns undefined.

Views

homepage.view.js

sap.ui.jsview("view.homepage", {
  getControllerName: function() {
   return "Webapp.controller.homepage";
  },
  createContent: function(oController) {
    var oTileSearchProd = new sap.m.StandardTile({
      title: "{i18n>tile_title_1}",
      press: [oController.goToProductSearch, oController]
    });
    var oTileTopRatedProd = new sap.m.StandardTile({
      title: "{i18n>tile_title_2}",
      press: [oController.goToProductAnalytics, oController]
    });
    var oTileCont = new sap.m.TileContainer({
      tiles: [oTileSearchProd, oTileTopRatedProd]
    });
    var oPage = new sap.m.Page({
      title: "{i18n>app_head}",
      enableScrolling: false,
      content: [oTileCont]
    });
    return oPage;
  }
});

Controllers

homepage.controller.js

sap.ui.controller("Webapp.controller.homepage", {
  onInit: function() {
    var i18nPath = "i18n/i18n.properties";
    var oi18nModel = new sap.ui.model.resource.ResourceModel({
      bundleUrl: i18nPath
    });
    sap.ui.getCore().setModel(oi18nModel, "i18n");
  },

  goToProductSearch: function(oEvt) {
    var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
    oRouter.navTo("idSearchProductPage");
  },

  goToProductAnalytics: function(oEvt) {
    var app = sap.ui.getCore().byId("idProductsAnalyticsPage");
    var oResourceBundle = app.getModel("i18n").getResourceBundle();
    var url = oResourceBundle.getText("LOGIN").toString().trim();
    sap.ui.getCore().setModel(new sap.ui.model.json.JSONModel(url), "barChart");
    var that = this;
    that.getOwnerComponent().getRouter().navTo("idProductsAnalyticsPage");
  }
});

App Descriptor (manifest.json)

{
  "_version": "1.12.0",
  "sap.app": {
    "id": "Webapp",
    "type": "application",
    "applicationVersion": {
      "version": "1.0.0"
    },
    "title": "{{appTitle}}",
    "description": "{{appDescription}}",
    "sourceTemplate": {
      "id": "servicecatalog.connectivityComponentForManifest",
      "version": "0.0.0"
    }
  },
  "sap.ui": {
    "technology": "UI5"
  },
  "sap.ui5": {
    "rootView": {
      "viewName": "Webapp.view.homepage",
      "type": "JS",
      "async": true,
      "id": "App"
    },
    "routing": {
      "config": {
        "routerClass": "sap.m.routing.Router",
        "viewType": "JS",
        "viewPath": "sap.ui.Webapp.view",
        "controlId": "app",
        "controlAggregation": "pages",
        "transition": "slide"
      },
      "routes": [
        {
          "pattern": "",
          "name": "homepage",
          "target": "homepage"
        },
        {
          "pattern": "SearchProductPage",
          "name": "SearchProductPage",
          "target": "SearchProductPage"
        },
        {
          "pattern": "ProductDetailPage",
          "name": "ProductDetailPage",
          "target": "ProductDetailPage"
        },
        {
          "pattern": "ProductAnalyticsPage",
          "name": "ProductAnalyticsPage",
          "target": "ProductAnalyticsPage"
        },
        {
          "pattern": "SearchProductPage",
          "name": "SearchProductPage",
          "target": "SearchProductPage"
        }
      ],
      "targets": {
        "homepage": {
          "viewName": "homepage"
        },
        "SearchProductPage": {
          "viewName": "SearchProductPage"
        },
        "ProductDetailPage": {
          "viewName": "ProductDetailPage"
        },
        "ProductAnalyticsPage": {
          "viewName": "ProductAnalyticsPage"
        }
      }
    }
  }
}

My index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
    <title>Divya Demo Project</title>
    <script
      src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js "
      id="sap-ui-bootstrap"
      data-sap-ui-libs="sap.m"
      data-sap-ui-theme="sap_bluecrystal"
      data-sap-ui-resourceroots='{"Webapp":"./"}'
    ></script>
    <script>
      sap.ui.localResources("view");
      var app = new sap.m.App({
        initialPage: "homePage",
      });
      app.addPage(sap.ui.view({
        id: "homePage",
        viewName: "view.homepage",
        type: sap.ui.core.mvc.ViewType.JS,
      }));
      app.addPage(sap.ui.view({
        id: "SearchProductPage",
        viewName: "view.SearchProductPage",
        type: sap.ui.core.mvc.ViewType.JS,
      }));
      app.placeAt("content");
    </script>
  </head>
  <body class="sapUiBody" role="application">
    <div id="content"></div>
  </body>
</html>

This is my project. everything is in JavaScript:

My project folder

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
Winona
  • 115
  • 1
  • 17

2 Answers2

4

Here is a sample app with JSView and navigating on click: https://embed.plnkr.co/qOnDlm.
(Update: JSView is deprecated since UI5 v1.90. Use Typed Views instead.)

Main Issue

The main issue is that your application is not evaluating manifest.json at all. In order to fetch the descriptor in the first place, your app needs to use sap/ui/core/ComponentContainer and UIComponent with metadata: { manifest: "json" }. These are completely missing in your index.html. I.e. the app doesn't even know that there are routing settings.

A ComponentContainer is needed since Components cannot be added to the UI without a container. And in Component.js, the metadata: { manifest: "json" } assignment tells the framework to fetch the app descriptor manifest.json which will be then evaluated with all the router settings.

ComponentContainer can be added to index.html declaratively without an inline-script using the sap/ui/core/ComponentSupport module. Please see the linked API reference for further guidance.

Other Issues

There are more inconsistencies with the guidelines which should be also fixed together with the main issue.

The neo-app.json being in the webapp folder whereas Component.js isn't.
✔️ For the proper folder structure, follow the topic Folder Structure: Where to Put Your Files. I.e. Component.js should be inside, neo-app.json outside of the webapp folder.

Using deprecated APIs as well as calling methods without requiring modules
✔️ Consult API reference which APIs to use instead of deprecated ones. E.g. defining controllers using sap.ui.controller should be replaced with Controller#extend.
✔️ Require sap/ui/core/UIComponent first, and then call UIComponent.getRouterFor.

Module name prefixes mismatching with base namespace.
✔️ For proper module registration according to the guideline, keep the general namespace consistent with the base resourceRoot namespace.

Also I see that the homepage view is assigned to sap.ui5/rootView too. Please avoid that.


Here are some snippets incorporating the above mentioned points:

  1. Given this folder structure..

  2. In index.html:

    <head>
      <!-- ... -->
      <script id="sap-ui-bootstrap" src="..."
        data-sap-ui-resourceRoots='{"myCompany.myApplication": "./"}'
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
        data-...><script>
    <head>
    <body id="content" class="sapUiBody">
      <div style="height: 100%;"
        data-sap-ui-component
        data-name="myCompany.myApplication"
        data-height="100%">
      </div>
    </body>
  3. In Component.js:

    return UIComponent.extend("myCompany.myApplication", {
      metadata: {
        manifest: "json"
      },
      init: function() {
        UIComponent.prototype.apply(this, arguments);
        this.getRouter().initialize();
      },
    });
  4. In manifest.json, "sap.ui5":

    {
      "rootView": {
        "viewName": "myCompany.myApplication.view.NotHomepage",
        "...": "..."
      },
      "routing": {
        "config": {
        "viewPath": "myCompany.myApplication.view",
        "...": "..."
      },
      "routes": [
        {
          "pattern": "",
          "name": "homepage",
          "target": "homepage"
        },
        "..."
      ],
      "...": "..."
    }
  5. In controllers

    sap.ui.define([ // e.g. controller/Homepage.controller.js
      "sap/ui/core/mvc/Controller",
      // ...,
      "sap/ui/core/UIComponent"
    ], function(Controller, /*...,*/ UIComponent) {
      "use strict";
      // 1. Stop using the deprecated sap.ui.controller.
      // 2. Convention: class name should be camel-case, starting with a capital letter (Homepage).
      // The same applies to all the other controllers and views.
      return Controller.extend("myCompany.myApplication.controller.Homepage", {
        goToProductSearch: function(oEvt) {
          const router = UIComponent.getRouterFor(this); // or without requiring UIComponent: this.getOwnerComponent().getRouter();
        },
        // ...
      });
    });
  6. In JS views:

    sap.ui.jsview("myCompany.myApplication.view.Homepage", { // e.g. view/Homepage.view.js
      getControllerName: function() {
        return "myCompany.myApplication.controller.Homepage";
      },
      // ...
    });

    Update: sap.ui.jsview is now fully deprecated. Use Typed Views instead!

Since the project seems relatively small, I'd suggest to start anew using the basic SAPUI5 template:

basic SAPUI5 template.

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
  • Thanks Boghyon, i can see my mistakes. As suggested i moved my manifest.json inside by Webapp and moved neo json outside the Webapp. I have also included the component container in index.html. So my root resource is Webapp. I still see my code is not able to manifest. "Failed to load component manifest from "Webapp/manifest.json". – Winona Mar 24 '20 at 21:00
  • @Winona It's hard to debug from here without code. Try comparing your code with the [sample plunk](https://embed.plnkr.co/qOnDlm) I gave in the answer, and tackle issues one by one. – Boghyon Hoffmann Mar 24 '20 at 21:47
  • @Winona I highly recommend to follow the learning path provided by the Demo Kit: https://openui5.hana.ondemand.com/topic/8b49fc198bf04b2d9800fc37fecbb218, especially the walkthrough. It addresses all the basic rules I mentioned in my answer. – Boghyon Hoffmann Mar 24 '20 at 22:14
0

maybe you should look first on the documentation

https://sapui5.hana.ondemand.com/1.36.6/docs/guide/e5200ee755f344c8aef8efcbab3308fb.html

view:

 createContent : function(oController) {
        var oTileSearchProd = new sap.m.StandardTile({
        title: "{i18n>tile_title_1}",
        press : [ oController.goToProductSearch, oController]
        }); 
        return new sap.m.Page({
            title: "Title Page 2",
            content: [
                oTileSearchProd 
            ]
        });
    }

and controller:

goToProductSearch: function()  {
        var router;
        router = sap.ui.core.UIComponent.getRouterFor(this);
        return router.navTo("SearchProductPage", null);
    }

also i would change the route conf. in your manifest for example try to build it for you

   "routing": {
    "config": {
        "viewType": "JS",
        "viewPath": "sapui5.app53.view",
        "targetControl":"idPageContainer",
        "targetAggregation": "pages",
        "routerClass": "sap.m.routing.Router"
    },
    "routes": [{
        "pattern": "",
        "name": "First",
        "view": "zjs_view_53_02",
        "targetAggregation": "pages"
    }, {
        "pattern": "second",
        "name": "Second",
        "view": "zjs_view_53_03",
        "targetAggregation": "pages"
    }]
}
Jünge alles
  • 491
  • 1
  • 5
  • 19
  • alles i am following that link. I have 4 pages actually in my project. My homepage has two tiles. Clicking on each should navigate to the respective pages. I have added all this in my router in my manifest.json. editor->routing. This is my component.js sap.ui.define([ "sap/ui/core/UIComponent", "sap/ui/model/json/JSONModel" ], function (UIComponent, JSONModel) { "use strict"; return UIComponent.extend("homepage.view", { metadata: { manifest: "json" }, init: function () { UIComponent.prototype.init.apply(this, arguments);this.getRouter().initialize(); – Winona Mar 23 '20 at 16:35
  • alles , i tried the above code in my view i was not able to add return new , it gave error . However i was able to add return router in controller but still got "TypeError: sap.ui.core.UIComponent.getRouterFor is not a function". – Winona Mar 23 '20 at 18:12
  • you need to change your manifest routing.. i post a example i found. Seems legit – Jünge alles Mar 23 '20 at 18:29