Bug reproduction
http://jsbin.com/dajexiraca/2/edit?html,js,console,output
Issue
The docs say you can trigger a select2:select event and pass data via params.data. However, my templateSelection code fails because additional data is missing. Consider the code sample below.
Code
javascript
// manually trigger the `select2:select` event
$('#example1').trigger({
type: 'select2:select',
params: {
data: {
customData: "Hello World" // NOT AVAILABLE INSIDE templateSelection function!!!
}
}
});
Related
this.getView().bindElement({
path: `/Employees('${this._userId}')`,
parameters: { expand: 'aaa,bbb,ccc' },
events: {
dataReceived: (oEvent) => {
this.getView().setBusy(false)
debugger
}
}
});
I can see data in the response of the $batch request.
When I put a breakpoint in the dataReceived function handler, I can also see the data via this.getView().getModel().getProperty(this.getView().getBindingContext().getPath()).
The parameter oEvent.mParameters.data exists, but the value is undefined.
If I leave out expand, the data is set. Do all entities of an associated entityset need to have an association to its parent?
This is by design according to the API reference of dataReceived:
dataReceived
[...] This event may also be fired when an error occurred.
Param
type
description
data
string
The data received; is undefined in error cases
You must have somewhere an error message in the $batch response, or the request was somehow aborted.
The missing data parameter is currently the only documented indicator for a failed request on bindObject/bindElement.
PS: See also https://github.com/SAP/openui5/issues/2263
Using this plugin as a reference, I have Flex configured to be able to send a call to a Twilio Studio IVR, after an agent has accepted a call.
I'd like to be able to send an incoming call back to Studio when an agent rejects a call (i.e. as soon as they click the reject button). I'm trying to do this by adding a listener to the plugin's init method:
flex.Actions.addListener("afterRejectTask", async (payload, abortFunction) => {
let url: string = payload.task.attributes.transferToIvrUrl;
let menu: string = 'hangup';
await request(url, { CallSid: payload.sid, menu });
});
See here for the full context -- I'm pretty much using that exact code, with the addition of this listener.
I'm getting this error message, and the call is not transferred anywhere.
twilio-flex.unbundled-react.min.js:1574 Error on afterRejectTask: SyntaxError: Unexpected token < in JSON at position 0
Here's additional context from the console, if that's helpful:
Additional info:
The url being requested is a Twilio function, which successfully returns a response like this:
<Response>
<Enqueue workflowSid="WWcc1a650e4175089538d754a6c2e15a98">
<Task>{"transferToIvrUrl": "https://my-twilio-function-service.twil.io/studio-flex-transfer-helper"}</Task>
</Enqueue>
</Response>
Any advice would be appreciated.
Ah, ok, so looking at that plugin I found the example Twilio Function that works with it. From what I can tell, this function is intended to be used in two places, either in Studio to transfer the call to Flex (though I'm not sure it's needed for that) or from Flex to transfer the call back to Studio. The thing that triggers the different response is whether you pass an argument called transferToIVRMenu with the request.
Your current request is not passing that argument, you currently have:
await request(url, { CallSid: payload.sid, menu });
which looks similar to the original plugin's request:
await request(transferToIvrUrl, { CallSid: call_sid, transferToIVRMenu });
The difference is in the second property in the object. When you just pass the name of the variable in an object, it expands to call the property the same name as the variable and set the value to the value within the variable. So the original request expands out to:
await request(transferToIvrUrl, { CallSid: call_sid, transferToIVRMenu: transferToIVRMenu });
but your request only expands to:
await request(url, { CallSid: payload.sid, menu: menu });
So you are passing a parameter called menu not transferToIVRMenu and that triggers the Function on the back end to return TwiML and not to update the call.
To fix this, you can update your plugin code to send the transferToIVRMenu parameter, like:
flex.Actions.addListener("afterRejectTask", async (payload, abortFunction) => {
let url: string = payload.task.attributes.transferToIvrUrl;
let menu: string = 'hangup';
await request(url, { CallSid: payload.sid, transferToIVRMenu: menu });
});
We upload a document from SAPUI5 to our SAP System using the CREATE_STREAM Method of the oData Service in ABAP. The creation of the document works fine.
What we would like to achieve is to get the response back to SAPUI5. Especially when there is an error during the creation of the document in the backend.
In Frontend we use the uploadSet Control.
...oUploadSet.uploadItem(oItem);
In the Backend we create a message with
...lo_message_container->add_message( iv_msg_type = /iwbep/cl_cos_logger=>error
iv_msg_number = '018'
iv_msg_id = lv_msg_id
iv_add_to_response_header = abap_true
)....
We can find the created message in the error protocol of our gateway server (/IWFND/ERROR_LOG). But how can this message be retrieved in SAPUI5 and used in the MessageManger Control?
We tried the onUploadCompleted Control but we can't find any response data there.
Can somebody explain how the response or a message header from the CREAT_STREAM method can be used in SAPUI5?
The "new" UploadSet control is kinda half-baked imo. The response will get lost in some internal method. This internal method will then trigger onUploadCompleted and you get nothing but useless information.
Lucky for us we can easily overwrite this internal stuff. UploadSet has an aggregation Uploader. We have to provide our own Uploader. Problem solved. Here is the line that needs to be modified.
sap.ui.define([
"sap/m/upload/Uploader",
...
], function (Uploader, ...) {
return Uploader.extend("my.custom.control.Uploader", {
uploadItem: function (oItem, aHeaders) {
// beginning of the method. take it from the official sources
oXhr.onreadystatechange = function () {
const oHandler = that._mRequestHandlers[oItem.getId()];
if (this.readyState === window.XMLHttpRequest.DONE && !oHandler.aborted) {
// we need to return the xhr object. it contains the response!
that.fireUploadCompleted({ item: oItem, xhr: oXhr });
}
};
// .. rest of the method
}
});
});
Use it like this
<mvc:View xmlns:custom="my.custom.control" ....>
<UploadSet items="....">
.....
<uploader>
<custom:Uploader uploadUrl="......"
uploadCompleted=".onUploadCompleted"
uploadStarted=".onUploadStarted" />
</uploader>
</UploadSet>
Edit: Your own uploader also means implementing your own event handlers (uploadAborted, uploadCompleted, uploadProgressed, uploadStarted). See the official documentation for more information about the events.
I'm trying to use the Autocomplete plugin to produce a search box similar to the one at IMDB, I want it to:
Show more than just text in the options.
To act like a link when an option is selected (as each option will be a unique record).
That, if the user chooses, they press the button and a search is performed on their input.
The docs say that there are 3 types of datasource it will work with:
A data source can be:
an Array with local data
a String, specifying a URL
a Callback
I can get the autocomplete to work with the 2nd option, but then there isn't the ability to transform the data returned, it just takes the JSON and puts it straight in the dropdown. This means the source url can only return data in the format {label: "blah", value: "blurg"}.
If I could inject a transformation function, then I could have the url return whatever JSON I like, the function would change the data into the format the autocomplete expects but also formatted as I wish, and all without changing the response served by the url (I'm not going to return HTML from there, only JSON).
e.g. The url could return this:
{ label:"Grosse Point Blank", id: 3, img:"/imgs/gpb.png",...}
and a transform function could mung it into something like this:
{ label:"<a href='/films/3/grosse-point-blank'><img src='/imgs/gpb.png' />Grosse Point Blank</a>", value="grosse-point-blank"}
I've tried using option 3, a callback, with a getJSON call, but I can't get it to work. The nearest code I've found to what I may need is here, but it has options that aren't listed in the current docs for Autocomplete and I don't understand how to use the response object.
Is there an example of using the callback method with an AJAX request, or how I can inject a function that transforms the code?
You can use the _renderItem() private method of autocomplete to format the return data. It looks like this:
$("#element").autocomplete({...}).data( "autocomplete" )._renderItem = function( ul, item ) {
//...
};
You can see the method definition here https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js#L520
An example of code that I have used:
$("#element").autocomplete({...})
.data("autocomplete")._renderItem = function( ul, item ) {
return $( "<li></li>" ) // create the list item
.data( "item.autocomplete", item ) // save the data to the DOM
.append( "<a>"+ item.label + "</a>" ) // add the HTML
.appendTo( ul ); // append to the UL
};
Here's a brief structure when using callback method.
source: function( request, response ) {
$.ajax({
...
success: function( data ) {
// do transformation of data here
response(data);
}
});
}
Quoted from your link, http://api.jqueryui.com/autocomplete/#option-source
The third variation, the callback, provides the most flexibility, and
can be used to connect any data source to Autocomplete. The callback
gets two arguments:
A request object, with a single property called "term", which refers
to the value currently in the text input. For example, when the user
entered "new yo" in a city field, the Autocomplete term will equal
"new yo".
A response callback, which expects a single argument to
contain the data to suggest to the user. This data should be filtered
based on the provided term, and can be in any of the formats described
above for simple local data (String-Array or Object-Array with
label/value/both properties). It's important when providing a custom
source callback to handle errors during the request. You must always
call the response callback even if you encounter an error. This
ensures that the widget always has the correct state.
Can someone help me understand the following code? I found it here.
It takes advantage of the JQuery UI Autocomplete with a remote source. I've commented the code as best I can and a more precise question follows it.
$( "#city" ).autocomplete({
source: function( request, response ) {
//request is an objet which contains the user input so far
// response is a callback expecting an argument with the values to autocomplete with
$.ajax({
url: "http://ws.geonames.org/searchJSON", //where is script located
dataType: "jsonp", //type of data we send the script
data: { //what data do we send the script
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: request.term
},
success: function( data ) { //CONFUSED!
response(
$.map(
data.geonames, function( item ) {
return {
label: item.name+(item.adminName1 ? ","+item.adminName1:"")+","+item.countryName,
value: item.name
}
}
)
);
}
});
}
});
As you can see, I don't understand the use of the success function and the response callback.
I know the success function literal is an AJAX option which is called when the AJAX query returns. In this case, it seems to encapsulate a call to the response callback? Which is defined where? I thought by definition of a callback, it should be called on its own?
Thanks!
The response object as defined by the documentation ("Overview" page):
A response callback, which expects a
single argument to contain the data to
suggest to the user. This data should
be filtered based on the provided
term, and can be in any of the formats
described above for simple local data
(String-Array or Object-Array with
label/value/both properties). It's
important when providing a custom
source callback to handle errors
during the request. You must always
call the response callback even if you
encounter an error. This ensures that
the widget always has the correct
state.
so, the 'response' argument is actually a callback, which must be called upon success of the ajax retrieval of autocomplete items.
Since your data will come back via AJAX, your code must update the widget manually. jQueryUI provides an argument as a function so that your code can do that update by calling the function.
You can see the response object defined in the declaration of the function used for the source option:
source: function( request, response )
You could even take the AJAX call out of the equation and do something like this:
source: function(request, response) {
response([{label:'foo', value: 'foo'},{label:'bar', value:'bar'}]);
}
Would immediately call the response callback with an array of label/value pairs for the widget.