Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member194491
Active Participant


Heads up: If your joining us here, this is Exercise 2 of 3 in the SAP Cloud Platform Technical Academy (Canadian Roadshow & SAP Blogs Edition). That means these tutorials or “exercises” are extremely well-documented and will walk you through every step with screenshots and instructions.




Summary of Exercise:

In this exercise you'll import your high-fidelity prototype from SAP BUILD in SAP Web IDE. You'll incorporate UI Logic to the Controller to advance your prototype into a full-functioning responsive application. The application will be able to communicate with API's on the SAP Cloud Platform, prompt users with Dialog Alerts, and translate texts from English to 7 (seven) different languages. You'll also deploy your application to run on the SAP Cloud Platform, which will then be accessible via a simple URL.

What will you use?

What will you learn?

  • Controller implementation for the SAPUI5 Model-View-Controller concept

    • Dropdown List control

    • Button-press

    • REST API Handling



  • Import a project into the SAP Web IDE Workspace

  • Navigate through the SAP API Business Hub

  • Generate an API Key from the SAP API Business Hub

  • Application Testing in SAP Web IDE

  • Deploy a HTML5 Application to SAP Cloud Platform


Result



 




Let's get started!


First, we need to access SAP Web IDE from our Services in the SAP Cloud Platform Cockpit.



From the left-hand side menu, Select Services and filter to the DevOps category. Select Web IDE. Do not select SAP Web IDE, Multi-Cloud Version.

The Multi-Cloud Version is based on a more capable and scalable open-source server-side foundation, and offers advanced features that are not available in the regular SAP Web IDE version. (If you would like to learn more about it, select here).



Once you've selected Web IDE, you'll see the service overview page. Simply select Go to Service to launch Web IDE.


Import your SAP BUILD prototype into SAP Web IDE


Now that you're in SAP Web IDE, you'll notice a few options down the left-hand side of the screen. You're currently on the Welcome screen. Below the Welcome (House) button, you have your Development (Workspace, </>), Learning Center, and Preferences.

For this exercise we'll do our work from Development (</>). Select </>.



Navigate to File > Import > From File System.



This will open the file explorer for your personal computer. Select our renamed SAP BUILD .ZIP file named sapTranslate.zip.

Ensure your import is as follows:

File: sapTranslate.zip
Import to: /sapTranslate
Extract Archive: ✓ (Checked)

Select OK.



Once your import is complete, you'll notice the sapTranslate folder under the larger Workspace folder. This means the .ZIP file has imported the structure of your application (which was created in SAP BUILD) and established it in SAP Web IDE.


Add onto the Controller


Incredible! That means you created 90% of your application already without writing a single line of code! Well, that ends here. Let's open the controller of the application under the sub-folder called controller. Open tranlateui.controller.js.

If you noticed, the controller is called "translateui". Remember, we gave it that name in SAP BUILD when we renamed the page template. That change cascaded down into the structure of this application and is reflected in the view and controller.



You're now going to add all of the remaining logic to your application. Create a few spaces between return BaseController.extend("generated.app.controller.translateui", { and handleRouteMatched: function(oEvent) { (between line 7 and 8).



Paste or write the following code to your controller:
		/*New Stuff*/
translateButtonPressed: function() {
var self = this;
var aLangName = ["German", "Spanish (Spain)", "French (France)", "Italian", "Japanese",
"Portuguese (Brazil)", "Chinese (Simplified)"
];
var aLangCode = ["de", "es", "fr", "it", "ja", "pt", "zh"];
var oldText = this.getView().byId("OldText").getValue();
var newLang = this.getView().byId("NewLang").getSelectedItem();
if (newLang !== null) {
//var oldLangCode = aLangCode[aLangName.indexOf(oldLang.mProperties.text)];
var newLangCode = aLangCode[aLangName.indexOf(newLang.mProperties.text)];
var data =
"{\r\n \"sourceLanguage\":en,\r\n \"targetLanguages\": [\r\n " + newLangCode +
" \r\n ],\r\n \"units\": [\r\n {\r\n \"value\":\"" + oldText + "\"\r\n }\r\n ]\r\n}";
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if (this.readyState === this.DONE) {
sap.m.MessageToast.show("Translated!");
self.getView().byId("NewText").setValue(JSON.parse(this.responseText).units[0].translations[0].value);
}
});
//setting request method
xhr.open("POST", "https://sandbox.api.sap.com/translationhub/api/v1/translate");
//adding request headers
xhr.setRequestHeader("Content-Type", "string");
xhr.setRequestHeader("Accept", "application/json; charset=utf-8");
xhr.setRequestHeader("APIKey", "YOUR_API_KEY");

//sending request
xhr.send(data);
} else {
var dialog = new sap.m.Dialog({
title: 'Missing Language',
type: 'Message',
state: 'Error',
content: new sap.m.Text({
text: "Please select a language."
}),
beginButton: new sap.m.Button({
text: 'OK',
press: function() {
dialog.close();
}
}),
afterClose: function() {
dialog.destroy();
}
});
dialog.open();
}
},
/*End of New Stuff*/

After you paste/write the code, open the context menu (by right-clicking anywhere on the code) and select Beautify to clean up your code structure.



One thing to note: We've added sensitive information, such as the endpoint URL and the API Key directly into the controller. In a typical enterprise application, we would leverage Destinations under Connectivity, from the SAP Cloud Platform Cockpit. 

Connectivity destinations are part of SAP Cloud Platform Connectivity and are used for the outbound communication of a cloud application to a remote system. They contain the connection details for the remote communication of an application. Connectivity destinations are represented by symbolic names that are used by on-demand applications to refer to remote connections. The result is an object that contains customer-specific configuration details, such as the URL of the remote system or service, the authentication type, and the relative credentials. This is much more secure than our method. Due to time constraints of the in-person Workshop, we leverage the non-recommended and less secure route to save time.  

Add our API Key from the SAP API Business Hub


Without closing SAP Web IDE, open a new tab in your browser, and navigate to api.sap.com. This is the SAP API Business Hub. The SAP API Business Hub is a Web-based application, a one-stop shop for all cloud integration content. You can also find sample apps, documentation, and links to demos.

We're going to generate an API Key that will allow our application to communicate with the SAP API. An application programming interface key (API key) is a code passed in by computer programs calling an application programming interface (API) to identify the calling program, its developer, or its user to the Web site.



Select Browse (with the magnifying glass icon next to it) in the middle-left side of your screen. It will open the list of all available APIs, Integration Flows (iFlows), and sample apps. Simply search "translate".



Select the "SAP Translation Hub". This will take you to the overview page of the REST API (ensure you're signed in by selecting Login on the top-right corner of your screen)



From the Artifacts tab, select "SAP Translation Hub" again.



Now, on this screen you will see a key icon on the top-right. By selecting that icon, you will be able to generate your API Key to use this API in your application. Select the Key icon.



Copy API Key; we will use it in the next step.



Navigate back to your SAP Web IDE window > controller sub-folder (in sapTranslate) >open translateui.controller.js. Find the part of your controller that requires "YOUR_API_KEY" (possibly on line 37). Paste the API Key in between the open/close quotes.



Your controller is now complete. We'll now build on top of our View.

Reference your Controller in the View


Now that we've added the remaining logic, we need to link it to the different parts of the view. What's the view? The view is the part of our application the end-user sees. For example, the Input field, a Dialog Alert, the target Language from the Dropdown List, and the translated text. These are all parts of the application that the end-user sees and uses to operate the application.

Navigate to the view sub-folder and open translateui.view.xml.



We're going to be linking the View to the Controller by adding IDs to specific controls in the application. For example, our application has target text that needs translating, a language in needs to be translated to, a Button to trigger the call to the REST API, and finally the result (the translated texts).

To start, let's add the following ID to our Input control (possibly on line 15). This is the control where the end-user enters the text that requires translation. It's also the control with the Placeholder, "What would you like to translate?".
id="OldText"



Next, let's add the following ID to our ComboBox (also known as the Dropdown List, possibly on line 23). This is the control that will allow the end-user to select their target language.
id="NewLang"



We'll now add the following ID to our other Input box (possibly on line 34). This is where the translated text will appear.
id="NewText"



Lastly, we'll add the following ID to our Button (possibly on line 40). We're adding the power to our Button that will allow it to initiate a call to the REST API with the text that needs to be translated, then return the translated text to us. We're also allowing the button to detect whether the user has selected a language when they select "Translate". If they haven't, then our application will alert them with a Dialog Alert box.
press="translateButtonPressed"


Test your SAP Translate application in SAP Web IDE


Congratulations! You've completed your SAP Translate application. But before we deploy it, it's important that we test it. SAP Web IDE has a built-in application testing feature.

Select your sapTranslate folder in your Development Workspace. Once it's selected, in the top toolbar on your screen, select Run > Run As > Web Application.



Select testFLPService.html.



Now, SAP Web IDE will open a simulated version of your application in sandbox in a new tab/window.



Feel free to test out its features (including the Dialog Alert box when you don't select a language). It's important to know everything works before we deploy it to the SAP Cloud Platform.


Deploy your SAP Translate application to the SAP Cloud Platform


Your app works - great! Now we can deploy it. Close the testing window and navigate back to SAP Web IDE.  Open the context menu (by right-clicking on the sapTranslate folder). Select Deploy > Deploy to SAP Cloud Platform.



Verify your information and the Activate box is checked. Select Deploy.



If all is successful, you should see the message "Successfully Deployed". Select Open the active version of the application.



This is open the live URL to your application. Feel free to test it on your desktop and mobile. Because we used the Responsive page template in SAP BUILD during Exercise #1, our application will automatically resize based on the screen's resolution.


Optional: Where to find your application's URL from the SAP Cloud Platform Cockpit


From the SAP Cloud Platform Cockpit, select Applications > HTML Applications from the left-hand side menu.



You'll see a list of all of your deployed HTML5 applications, including saptranslate. Select saptranslate. Once selected, you find the Application URL.



Congratulations- you've completed Exercise #2! Next, learn how to create, configure, and register your application to a SAP Fiori Launchpad.

Continue with Exercise 3 of 3.


11 Comments
karthikarjun
Active Contributor
0 Kudos

Hi, It is an awesome work.

Can you please help me why I am getting this error in the console?

XMLHttpRequest cannot load https://sandbox.api.sap.com/translationhub/api/v1/translate. Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. Origin ‘https://webidetesting0459451-p<ID>trial.dispatcher.hanatrial.ondemand.com’ is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

 

2) XMLHTTP Rrequest moves to success call but it returns empty string ?

 

Regards,

Karthik A

 

former_member194491
Active Participant
0 Kudos
Hi Karthik,

Thanks for trying the exercise. Can you confirm that when you run your app in Web IDE's Sandbox environment, you're running it as a Web Application (Run testFLPService.html).

-Patrick
Former Member
0 Kudos


I am running into a similar problem ...

 
former_member194491
Active Participant
0 Kudos
Does your issue persist after deployment outside of Web IDE?
Former Member
0 Kudos
Yes it does persist after deployment outside of web IDE . I also noticed this error when it tried to load the page

failed to load 'generated/app/Component-preload.js' from ../Component-preload.js: 404 - Not Found
Caused by: undefined
former_member194491
Active Participant
0 Kudos
You may have made an error somewhere on the controller. Below is my controller:
sap.ui.define(["sap/ui/core/mvc/Controller",
"sap/m/MessageBox",
"sap/ui/core/routing/History"
], function(BaseController, MessageBox, History) {
"use strict";

return BaseController.extend("generated.app.controller.translateui", {

/*New Stuff*/
translateButtonPressed: function() {
var self = this;
var aLangName = ["German", "Spanish (Spain)", "French (France)", "Italian", "Japanese",
"Portuguese (Brazil)", "Chinese (Simplified)"
];
var aLangCode = ["de", "es", "fr", "it", "ja", "pt", "zh"];
var oldText = this.getView().byId("OldText").getValue();
var newLang = this.getView().byId("NewLang").getSelectedItem();
if (newLang !== null) {
//var oldLangCode = aLangCode[aLangName.indexOf(oldLang.mProperties.text)];
var newLangCode = aLangCode[aLangName.indexOf(newLang.mProperties.text)];
var data =
"{\r\n \"sourceLanguage\":en,\r\n \"targetLanguages\": [\r\n " + newLangCode +
" \r\n ],\r\n \"units\": [\r\n {\r\n \"value\":\"" + oldText + "\"\r\n }\r\n ]\r\n}";
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if (this.readyState === this.DONE) {
sap.m.MessageToast.show("Translated!");
self.getView().byId("NewText").setValue(JSON.parse(this.responseText).units[0].translations[0].value);
}
});
//setting request method
xhr.open("POST", "https://sandbox.api.sap.com/translationhub/api/v1/translate");
//adding request headers
xhr.setRequestHeader("Content-Type", "string");
xhr.setRequestHeader("Accept", "application/json; charset=utf-8");
xhr.setRequestHeader("APIKey", "YOUR-API-KEY");

//sending request
xhr.send(data);
} else {
var dialog = new sap.m.Dialog({
title: 'Missing Language',
type: 'Message',
state: 'Error',
content: new sap.m.Text({
text: "Please select a language."
}),
beginButton: new sap.m.Button({
text: 'OK',
press: function() {
dialog.close();
}
}),
afterClose: function() {
dialog.destroy();
}
});
dialog.open();
}
},
/*End of New Stuff*/

handleRouteMatched: function(oEvent) {
var oParams = {};

if (oEvent.mParameters.data.context || oEvent.mParameters.data.masterContext) {
var oModel = this.getView ? this.getView().getModel() : null;
if (oModel) {
oModel.setRefreshAfterChange(true);

if (oModel.hasPendingChanges()) {
oModel.resetChanges();
}
}

this.sContext = oEvent.mParameters.data.context;
this.sMasterContext = oEvent.mParameters.data.masterContext;

if (!this.sContext) {
this.getView().bindElement("/" + this.sMasterContext, oParams);
} else {
this.getView().bindElement("/" + this.sContext, oParams);
}

}

},
onInit: function() {
this.mBindingOptions = {};
this.oRouter = sap.ui.core.UIComponent.getRouterFor(this);
this.oRouter.getTarget("translateui").attachDisplay(jQuery.proxy(this.handleRouteMatched, this));

}
});
}, /* bExport= */ true);

If not, verify the IDs in your view.
former_member185575
Participant
0 Kudos
Hi Patrick!

 

You state:

One thing to note: We’ve added sensitive information, such as the endpoint URL and the API Keydirectly into the controller. In a typical enterprise application, we would leverage Destinations under Connectivity, from the SAP Cloud Platform Cockpit. 

I know how to maintain a Destination with its endpoint URL - but I have no idea how to maintain the additional header field for the API key? How would you do that?



 
former_member185575
Participant
0 Kudos
Hi Patrick,

you didn't respond to my email or this post.

In the meantime I wrote a PHP proxy script to secure the access to the machine learning API without setting the HEADER field in the frontend:

https://github.com/denisenepraunig/php-proxy-sap-machinelearning-api
vodela
Active Participant
0 Kudos
I created build project and imported into WEBIDE Based on SAP ES4 EPM Model– I changed the mainfest.json to point to Server ES4 and added ES4 Entry to neo.app – The Server is not getting called – the server is not getting called.  I Tested the same with app with a project createdwebide – it works fine but not the one imported from buid.

Ramesh

 
Jacques-Antoine
Active Participant
Awesome blog Patrick!!! Let's go to the third part. 🙂
lars_gregori
Advisor
Advisor
0 Kudos
Hi Denise,

with a trial (or GA) account you could use the Production URLs which are listed on the Details page e.g. https://saptranslation-{subaccountname}.hanatrial.ondemand.com.

This allows you to use AppToAppSSO or BasicAuthentication as Authentication at the Destination Configuration.