在SAP WebClient UI里使用AJAX进行异步数据读取
For POC purpose I need to implement the AJAX functionality in Webclient UI component. The UI component has only one input field:
Once type “a” into the input field, it immediately displays all the records in the database table SCARR whose column carrname contains the character “a” ( without any other operation like manual refresh)
change the value in the input field, the page will display the latest matched result automatically:
Here below are the steps how to build this very simple UI component which implement AJAX functionality:
(1) Create a new UI component and a new empty view
In the html view, paste the following code: Part1
<%@page language="abap"%>
<%@extension name="htmlb" prefix="htmlb"%>
<%
data: lv_url TYPE string,
lv_query type string.
lv_query = 'query='.
lv_url = cl_crm_web_utility=>create_url( iv_path = '/sap/crm/zajax'
iv_query = lv_query
iv_in_same_session = 'X' ).
%>
Since we will send asynchronous xml request to ABAP backend to query records from database table. The query must be implemented in ABAP backend. Here I will create a new ICF service node to accomplish such query. The creation of ICF node and its handler class will be discussed later. In this step we just need to pass in the ICF node path ‘/sap/crm/zajax’ to metod create_url. That method will return the url which would be used as prefix of the final url of the asynchronous request to be sent to ABAP backend.
Part2
Here we define the four JavaScript functions:
function GetXmlHttpObject(){
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
comment: this function is designed to support different kinds of browsers.
function stateChanged() {
if (xmlhttp.readyState == 4) {
document.getElementById("result").innerHTML = xmlhttp.responseText;
document.getElementById("result").style.border = "1px solid #A5ACB2";
}
}
comment: this function is callback function which will automatically be called when the backend response returned by our ICF handler class is available to consume ( that means, the result is ready to be displayed in the frontend UI )
function getRequestURL(str) {
var url = "<%= lv_url %>" + str;
url = url + "&sid=" + Math.random();
return url;
}
comment: this function will assemble the final url which is to be sent to ABAP backend. The ABAP variable lv_url contains the full url of our icf node appended with request prefix “query=”. So within this function we just simply concatenate the string which is typed by end user in the input field.
function showResult(str){
if (str.length == 0 ) {
document.getElementById("result").innerHTML = "";
document.getElementById("result").style.border = "0px";
return;
}
xmlhttp = GetXmlHttpObject();
if (xmlhttp == null ){
alert ("Your browser does not support XML HTTP Request");
return;
}
var requesturl = getRequestURL(str);
xmlhttp.onreadystatechange = stateChanged ;
xmlhttp.open("GET",requesturl,true);
xmlhttp.send(null);
}
comment: we will bind this function to event onkeyup of input field, so that once we finish the typing in input field, it will be called. Within it, the asynchronous xml request is sent. We bind our callback function “stateChanged” to xmlhttp.onreadystatechange and do not need to care about when to call it – instead the framework will call this callback automatically when it should be called.
Part3
<body>
input name: <input type="text" id="fname" onkeyup="showResult(this.value)" />
<div id = "result" ></div>
</body>
comment: just bind the event handler to event “onkeyup”.
for the complete source code which could directly be “Ctrl + C” and “Ctrl + V”, please find it in attachment.
(2) Create a new ICF node and its handler class
Use tcode SICF, create a new ICF node.
The path should be consistent with the hardcode path in the method call in step one:
lv_url = cl_crm_web_utility=>create_url( iv_path = '/sap/crm/zajax'
iv_query = lv_query
iv_in_same_session = 'X' ).
Create a new handler class which implement interface IF_HTTP_EXTENSION:
Implement the method HANDLE_REQUEST as below:
method IF_HTTP_EXTENSION~HANDLE_REQUEST.
DATA: lv_input_str TYPE string,
lv_html TYPE string,
lt_scarr TYPE TABLE OF scarr.
FIELD-SYMBOLS: <fs_scarr> TYPE scarr.
lv_input_str = server->request->get_form_field( 'query' ).
SELECT * FROM scarr INTO TABLE lt_scarr.
IF strlen( lv_input_str ) > 0.
LOOP AT lt_scarr ASSIGNING <fs_scarr>.
FIND lv_input_str IN <fs_scarr>-carrname IGNORING CASE.
CHECK sy-subrc = 0.
IF strlen( lv_html ) = 0.
CONCATENATE `<a href=’` <fs_scarr>-url `’ target=’_blank’>`
<fs_scarr>-carrname `</a>` INTO lv_html.
ELSE.
CONCATENATE lv_html `<br />` `<a href=’` <fs_scarr>-url `’ target=’_blank’>`
<fs_scarr>-carrname `</a>` INTO lv_html.
ENDIF.
ENDLOOP.
ENDIF.
IF strlen( lv_html ) = 0.
lv_html = '<no suggestion>'.
ENDIF.
server->response->set_cdata( lv_html ).
endmethod.
Monitor AJAX request and response in Chrome
It is very convenient to monitor AJAX behavior via developer tool in Chrome. Launch the U component with Chrome, click F12 to open developer tool. Then mark the checkbox “Any XHR” under “XHR Breakpoints”.
So that once there is a AJAX request sent from your application, the developer tool will automatically stop at the very code in which the XHR ( XML Header Request ) is sent: Switch to debug mode, and then type a character like “a” in the input field, the session will stop – The UI becomes gray and there is a tooltip “Paused in debugger” in the top-right part of the window:
In the left-most part of development tool, you can observe which view the AJAX request is sent from. In our example from prefix “bspwd_cmp_test” we could judge that currently our ui component is launched in test mode ( by clicking the test button in UI Component Workbench); In the middle part we could see the exact line where the request is sent;
In the right most part we could check the detail value of variables used in JavaScript and the function callstack, just the same logic as ABAP debugger. For example we could get the detail of XHR like request url, and what character end user has input.
click F10 to step over until the response is returned from ABAP backend.
Put the mouse into field “responseText” and it will display the complete content of it:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Unet实现文档图像去噪、去水印
- 「influxDB 原理与实践(一)」安装部署,实现基础的添加删除查询功能
- 「influxDB 原理与实践(二)」详解influxDB的写入与查询
- Nginx系列:https配置
- 笛卡尔积、等值连接、自然连接、外连接一文看懂
- nginx系列:常用利用shell统计日志
- Nginx系列:图片过滤处理
- Nginx系列:几款负载均衡第三方插件的安装与使用
- 「高并发通信框架Netty4 源码解读(三)」NIO缓冲区Buffer详解
- UML类图符号:各种关系说明以及举例
- 「高并发通信框架Netty4 源码解读(四)」NIO缓冲区之字节缓冲区ByteBuffer详解
- 「influxDB 原理与实践(三)」连续查询
- 为什么使用OPA而不是原生的Pod安全策略?
- 浅入浅出 Java ConcurrentHashMap
- 「高并发通信框架Netty4 源码解读(五)」NIO通道Channel详解