** Я могу присудить награду, даже если она решит мою проблему! **
Я хочу вызвать ActionImport из SAPUI5 с использованием API OData v4.
Моим бизнес-требованием является отправка «идентификатора студента» для обновления / создания «TeachingSession». Когда пользователь выбирает «студент» из поля со списком и нажимает кнопку «Начать сеанс», я хочу отправить идентификатор выбранного студента. При нажатии этой кнопки я вызываю функцию «startSession» в контроллере.
Но я не могу запустить ActionImport из-за неправильного кодирования.
Я вижу ошибку ниже, когда я выполняю код ниже .
Не удалось выполнить / TeachingSessions ('3') / OnlineTeaching.UpdateTeachingSession (...) - ошибка: ожидается одна перегрузка, но найдено 0 для / TeachingSessions ('3') / OnlineTeaching .UpdateTeachingSession (...)
Ниже приведена схема OData:
<?xml version='1.0' encoding='UTF-8'?>
<edmx:Edmx Version="4.0"
xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm"
Namespace="OnlineTeaching">
<EntityType Name="Student">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" />
<Property Name="name" Type="Edm.String" />
<Property Name="email" Type="Edm.String" />
<Property Name="skypeid" Type="Edm.String" />
<NavigationProperty Name="Schedules" Type="Collection(OnlineTeaching.Schedule)" Partner="Student" />
<NavigationProperty Name="TeachingSessions" Type="Collection(OnlineTeaching.TeachingSession)" Partner="Student" />
</EntityType>
<EntityType Name="Schedule">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" />
<Property Name="weekday" Type="Edm.String" />
<Property Name="time" Type="Edm.String" />
<Property Name="timezone" Type="Edm.String" />
<NavigationProperty Name="Student" Type="OnlineTeaching.Student" Partner="Schedules" />
</EntityType>
<EntityType Name="TeachingSession">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Int32" />
<Property Name="date" Type="Edm.Date" />
<Property Name="startTime" Type="Edm.String" />
<Property Name="endTime" Type="Edm.String" />
<Property Name="timezone" Type="Edm.String" />
<NavigationProperty Name="Student" Type="OnlineTeaching.Student" Partner="TeachingSessions" />
</EntityType>
<Action Name="UpdateTeachingSession">
<Parameter Name="session_id" Type="Edm.Int32" />
<Parameter Name="student_id" Type="Edm.Int32" />
</Action>
<EntityContainer Name="Container">
<ActionImport Name="UpdateTeachingSession" Action="UpdateTeachingSession"/>
<EntitySet Name="Students" EntityType="OnlineTeaching.Student">
<NavigationPropertyBinding Path="Schedules" Target="Schedules" />
<NavigationPropertyBinding Path="TeachingSessions" Target="TeachingSessions" />
</EntitySet>
<EntitySet Name="Schedules" EntityType="OnlineTeaching.Schedule">
<NavigationPropertyBinding Path="Student" Target="Students" />
</EntitySet>
<EntitySet Name="TeachingSessions" EntityType="OnlineTeaching.TeachingSession">
<NavigationPropertyBinding Path="Student" Target="Students" />
</EntitySet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
SAPUI5 Просмотр кода:
<Table
id="teachingSessionsTable"
growing="true"
growingThreshold="3"
items="{
path: '/TeachingSessions',
parameters: {
$count: true
,'expand': 'Student'
}
}"
mode="SingleSelectLeft">
<!-- ,$$updateGroupId : 'peopleGroup'
// inside item aggregation
,
events:{
change: '.onChangeHandler'
}
-->
<headerToolbar>
<OverflowToolbar>
<content>
<ToolbarSpacer/>
<SearchField
id="searchField"
width="20%"
placeholder="{i18n>searchFieldPlaceholder}"
enabled="{= !${appView>/hasUIChanges}}"
search=".onSearch"/>
<Button
id="addTeachingSessionButton"
icon="sap-icon://add"
tooltip="Create TeachingSession"
press=".onCreate">
<layoutData>
<OverflowToolbarLayoutData priority="NeverOverflow"/>
</layoutData>
</Button>
<Button
id="deleteTeachingSessionButton"
icon="sap-icon://delete"
tooltip="Delete TeachingSession"
press=".onDelete">
<layoutData>
<OverflowToolbarLayoutData priority="NeverOverflow"/>
</layoutData>
</Button>
<Button
id="refreshTeachingSessionsButton"
icon="sap-icon://refresh"
enabled="{= !${appView>/hasUIChanges}}"
tooltip="Refresh TeachingSession"
press=".onRefresh"/>
<Button
id="sortTeachingSessionsButton"
icon="sap-icon://sort"
enabled="{= !${appView>/hasUIChanges}}"
tooltip="Sort by Name/Description (placeholder)"
press=".onSort"/>
</content>
</OverflowToolbar>
</headerToolbar>
<columns>
<Column id="idColumn">
<Text text="Id"/>
</Column>
<!-- <Text text="{i18n>idLabelText}"/> -->
<Column id="dateColumn">
<Text text="Date"/>
<!-- <Text text="{i18n>dateLabelText}"/> -->
</Column>
<Column id="startTimeColumn">
<Text text="StartTime"/>
<!-- <Text text="{i18n>startTimeLabelText}"/> -->
</Column>
<Column id="endTimeColumn">
<Text text="EndTime"/>
<!-- <Text text="{i18n>endTimeLabelText}"/> -->
</Column>
<Column id="timezoneColumn">
<Text text="Timezone"/>
<!-- <Text text="{i18n>timezoneLabelText}"/> -->
</Column>
<Column>
<Text text="Id (Student)"/>
</Column>
<Column>
<Text text="Action"/>
</Column>
</columns>
<items>
<ColumnListItem id="table_col">
<cells>
<Input
value="{id}"
visible="false"
valueLiveUpdate="true"
liveChange=".onInputChange"/>
</cells>
<cells>
<Input value="{date}"
valueLiveUpdate="true"
/> <!-- liveChange=".onInputChange" -->
</cells>
<cells>
<Input
id="startTime"
value="{startTime}"
valueLiveUpdate="true"
liveChange=".onInputChange"/>
</cells>
<cells>
<Input
id="endTime"
value="{endTime}"
valueLiveUpdate="true"
liveChange=".onInputChange"/>
</cells>
<cells>
<Input
value="{timezone}"
valueLiveUpdate="true"
liveChange=".onInputChange"/>
</cells>
<!--
<cells>
<Text id="TeachingSession_Student_id_source" text="{Student/id}" visible="true" />
</cells>
-->
<cells>
<ComboBox id="student_id_combo_box"
showSecondaryValues= "true"
filterSecondaryValues= "true"
items="{
path: '/Students',
sorter: { path: 'name' },
templateShareable: true
}"
change=".handleStudentSelection"
>
<core:ListItem key="{id}" text="{name}" additionalText="{skypeid}"/>
</ComboBox>
</cells>
<cells>
<Button text="Start Session" press=".startSession" />
</cells>
</ColumnListItem>
</items>
</Table>
Мой код контроллера SAPUI5 - как показано ниже:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast",
"sap/m/MessageBox",
"sap/ui/model/Sorter",
"sap/ui/model/Filter",
"sap/ui/model/FilterOperator",
"sap/ui/model/FilterType",
"sap/ui/model/json/JSONModel",
"sap/base/Log"
], function (Controller, MessageToast, MessageBox, Sorter, Filter, FilterOperator, FilterType, JSONModel, Log) {
"use strict";
return Controller.extend("sap.ui.core.tutorial.odatav4.controller.TeachingSession", {
/**
* Hook for initializing the controller
*/
onInit : function () {
var oMessageManager = sap.ui.getCore().getMessageManager(),
oMessageModel = oMessageManager.getMessageModel(),
oMessageModelBinding = oMessageModel.bindList("/", undefined, [],
new Filter("technical", FilterOperator.EQ, true)),
oViewModel = new JSONModel({
busy : false,
hasUIChanges : false,
usernameEmpty : true,
order : 0
});
this.getView().setModel(oViewModel, "appView");
this.getView().setModel(oMessageModel, "message_layers");
oMessageModelBinding.attachChange(this.onMessageBindingChange, this);
this._bTechnicalErrors = false;
//this.getView().getModel().setDefaultBindingMode(BindingMode.OneWay);
},
/* =========================================================== */
/* begin: event handlers */
/* =========================================================== */
onChangeHandler: function(oEvent){
var eventName = oEvent.getParameter("reason");
console.log("Change: Event raised: " + eventName + ", timestamp = " + new Date().getTime());
},
onSelect_tier_id: function(oEvt){
var selectedTierId = oEvt.getSource().getSelectedKey();
this._selectRowOfChange( oEvt );
var selectedItem = this.byId( "teachingSessionsTable" ).getSelectedItem(); // row is same as item here
var oCells = selectedItem.getCells();
for( var i=0; i < oCells.length; i++ ){
if( oCells[i].getId().match( "tier_id_selected" ) ){
oCells[i].setValue( selectedTierId );
}
}
this.onInputChange( oEvt );
},
fnFormatter: function(text, key) {
var sText = "";
if (text && key) {
sText += (text + " (" + key + ")");
} else if (text) {
sText += text;
} else if (key) {
sText += key;
}
return sText;
},
_getDateStringToday: function(){
var today = new Date();
const year = today.getFullYear();
const month = today.getMonth();
month = month + 1;
const day = today.getDate();
var dateString = year + "/" + month + "/" + day;
return dateString;
},
handleStudentSelection: function(oEvent){
var oValidatedComboBox = oEvent.getSource(),
sSelectedKey = oValidatedComboBox.getSelectedKey(),
sValue = oValidatedComboBox.getValue();
if (!sSelectedKey && sValue) {
oValidatedComboBox.setValueState("Error");
oValidatedComboBox.setValueStateText("Select from existing Student list! If the student does not exist, you may have to add the student first");
} else {
oValidatedComboBox.setValueState("None");
this.byId("selectedStudentId").setValue( sSelectedKey );
}
},
startSession: function(oEvt){
this._selectRowOfChange( oEvt );
var selectedItem = this.byId( "teachingSessionsTable" ).getSelectedItem();
var cells = selectedItem.getCells();
/* Will be uncommented after action import resolution
// 1. Update the Start Time for the session row
var now = new Date();
var startTime = now.getHours() + ":" + now.getMinutes();
cells[2].setValue( startTime );
this._setUIChanges(true);
*/
// 2. Update the selected student id for this session row
var operation = this.getView().getModel().bindContext("/TeachingSessions('"+ cells[0].getValue() + "')/OnlineTeaching.UpdateTeachingSession(...)");
//var operation = this.getView().getModel().bindContext("/UpdateTeachingSession(...)");
operation.setParameter( "OnlineTeaching.UpdateTeachingSession.session_id", cells[0].getValue() );
operation.setParameter( "OnlineTeaching.UpdateTeachingSession.student_id", this.byId("selectedStudentId").getValue() );
operation.execute('$direct');
/*
.then(function () {
//oModel.refresh();
MessageToast.show("submitted action but need to see the response");
}.bind(this), function (oError) {
MessageBox.error(oError.message);
}
);
*/
/*
var oBinding = this.byId( "teachingSessionsTable" ).getSelectedItem().getBindingContext(); //this.byId("teachingSessionsTable").getBinding();
oBinding.setParameter("OnlineTeaching.UpdateTeachingSession.session_id", cells[0].getValue());
oBinding.setParameter("OnlineTeaching.UpdateTeachingSession.student_id", this.byId("selectedStudentId").getValue());
oBinding.setParameter("session_id", cells[0].getValue());
oBinding.setParameter("student_id", this.byId("selectedStudentId").getValue());
//oEvt.getSource().getParent().getBindingContext()
var oList = this.byId( "teachingSessionsTable" );
var oBinding = oList.getBinding("items");
//oContext = oBinding.
oBinding.execute();
*/
//this._setUIChanges(true);
},
/**
* Create a new entry.
*/
onCreate : function () {
var oList = this.byId( "teachingSessionsTable" );
//var dateString = this._getDateStringToday();
var oBinding = oList.getBinding("items"),
// Create a new entry through the table's list binding
// You may need to change the column name in place of "description"
oContext = oBinding.create({
"date" : null,
"startTime" : null ,
"endTime" : null ,
"timezone" : null
,
"Student@odata.bind": 1 });
this._setUIChanges(true);
this.getView().getModel("appView").setProperty("/usernameEmpty", true);
// Select and focus the table row that contains the newly created entry
oList.getItems().some(function (oItem) {
if (oItem.getBindingContext() === oContext) {
oItem.focus();
oItem.setSelected(true);
return true;
}
});
},
/**
* Delete an entry.
*/
onDelete : function () {
var oSelected = this.byId( "teachingSessionsTable" ).getSelectedItem();
if (oSelected) {
oSelected.getBindingContext().delete("$direct").then(function () {
MessageToast.show(this._getText("deletionSuccessMessage"));
}.bind(this), function (oError) {
MessageBox.error(oError.message);
});
}
},
/**
* Copies tier_id value from placeholder column to actual column
*/
_copyToInputField: function( oCells, value ){
for( var i=0; i < oCells.length; i++ ){
if( oCells[i].getId().match( "tier_id_actual" ) ){
oCells[i].setValue( value );
}
}
},
/**
* Selects the row of a table in which the user is making change of any field
*/
_selectRowOfChange: function(oEvt){
// Select the row of input change
var oFieldId = oEvt.getSource().getParent().getId();
this.byId( "teachingSessionsTable" ).setSelectedItemById( oFieldId, true);
},
/**
* Lock UI when changing data in the input controls
* @param {sap.ui.base.Event} oEvt - Event data
*/
onInputChange : function (oEvt) {
this._selectRowOfChange( oEvt );
if (oEvt.getParameter("escPressed")) {
this._setUIChanges();
} else {
this._setUIChanges(true);
// Check if the id in the changed table row is empty and set the appView property accordingly
if (oEvt.getSource().getParent().getBindingContext().getProperty("id")) {
this.getView().getModel("appView").setProperty("/usernameEmpty", false);
}
}
},
/**
* Refresh the data.
*/
onRefresh : function () {
var oBinding = this.byId( "teachingSessionsTable" ).getBinding("items");
if (oBinding.hasPendingChanges()) {
MessageBox.error(this._getText("refreshNotPossibleMessage"));
return;
}
oBinding.refresh();
MessageToast.show(this._getText("refreshSuccessMessage"));
},
/**
* Reset any unsaved changes.
*/
onResetChanges : function () {
this.byId( "teachingSessionsTable" ).getBinding("items").resetChanges();
this._bTechnicalErrors = false; // If there were technical errors, cancelling changes resets them.
this._setUIChanges(false);
},
/**
* Reset the data source.
*/
onResetDataSource : function () {
var oModel = this.getView().getModel(),
oOperation = oModel.bindContext("/ResetDataSource(...)");
oOperation.execute().then(function () {
oModel.refresh();
MessageToast.show(this._getText("sourceResetSuccessMessage"));
}.bind(this), function (oError) {
MessageBox.error(oError.message);
}
);
},
/**
* Save changes to the source.
*/
onSave : function () {
var fnSuccess = function () {
this._setBusy(false);
MessageToast.show(this._getText("changesSentMessage"));
this._setUIChanges(false);
}.bind(this);
var fnError = function (oError) {
this._setBusy(false);
this._setUIChanges(false);
MessageBox.error(oError.message);
}.bind(this);
this._setBusy(true); // Lock UI until submitBatch is resolved.
this.getView().getModel().submitBatch("peopleGroup").then(fnSuccess, fnError);
this._bTechnicalErrors = false; // If there were technical errors, a new save resets them.
},
/**
* Search for the term in the search field.
*/
onSearch : function () {
var oView = this.getView(),
sValue = oView.byId("searchField").getValue(),
oFilter = new Filter("description", FilterOperator.Contains, sValue);
oView.byId( "teachingSessionsTable" ).getBinding("items").filter(oFilter, FilterType.Application);
},
/**
* Sort the table according to the Description.
* Cycles between the three sorting states "none", "ascending" and "descending"
*/
onSort : function () {
var oView = this.getView(),
aStates = [undefined, "asc", "desc"],
aStateTextIds = ["sortNone", "sortAscending", "sortDescending"],
sMessage,
iOrder = oView.getModel("appView").getProperty("/order");
// Cycle between the states
iOrder = (iOrder + 1) % aStates.length;
var sOrder = aStates[iOrder];
oView.getModel("appView").setProperty("/order", iOrder);
// below column name "description" should be changed as per the requirement
oView.byId( "teachingSessionsTable" ).getBinding("items").sort(sOrder && new Sorter("description", sOrder === "desc"));
sMessage = this._getText("sortMessage", [this._getText(aStateTextIds[iOrder])]);
MessageToast.show(sMessage);
},
onMessageBindingChange : function (oEvent) {
var aContexts = oEvent.getSource().getContexts(),
aMessages,
bMessageOpen = false;
if (bMessageOpen || !aContexts.length) {
return;
}
// Extract and remove the technical messages
aMessages = aContexts.map(function (oContext) {
return oContext.getObject();
});
sap.ui.getCore().getMessageManager().removeMessages(aMessages);
this._setUIChanges(true);
this._bTechnicalErrors = true;
MessageBox.error(aMessages[0].message, {
id : "serviceErrorMessageBox_TeachingSessions",
onClose : function () {
bMessageOpen = false;
}
});
bMessageOpen = true;
},
/* =========================================================== */
/* end: event handlers */
/* =========================================================== */
/**
* Convenience method for retrieving a translatable text.
* @param {string} sTextId - the ID of the text to be retrieved.
* @param {Array} [aArgs] - optional array of texts for placeholders.
* @returns {string} the text belonging to the given ID.
*/
_getText : function (sTextId, aArgs) {
return this.getView().getModel("i18n").getResourceBundle().getText(sTextId, aArgs);
},
/**
* Set hasUIChanges flag in View Model
* @param {boolean} [bHasUIChanges] - set or clear hasUIChanges
* if bHasUIChanges is not set, the hasPendingChanges-function of the OdataV4 model determines the result
*/
_setUIChanges : function (bHasUIChanges) {
if (this._bTechnicalErrors) {
// If there is currently a technical error, then force 'true'.
bHasUIChanges = true;
} else if (bHasUIChanges === undefined) {
bHasUIChanges = this.getView().getModel().hasPendingChanges();
}
var oModel = this.getView().getModel("appView");
oModel.setProperty("/hasUIChanges", bHasUIChanges);
},
/**
* Set busy flag in View Model
* @param {boolean} bIsBusy - set or clear busy
*/
_setBusy : function (bIsBusy) {
var oModel = this.getView().getModel("appView");
oModel.setProperty("/busy", bIsBusy);
}
});
});