cancel
Showing results for 
Search instead for 
Did you mean: 

SAPUI5 Add new item to odata with a form

Former Member
0 Kudos

hello,
I have a mocker server already built and all items from the mock.json are displayed in a list. now I wand add the new item to OData with a Simpleform. In tutorial is implemented with submitChanges() and for cancel button with resetChanges(). but there are not work in my Page.

this is my Controller.js

sap.ui.define(['sap/ui/core/mvc/Controller', 
'timeTrackertimeTracker/controller/BaseController', 
'sap/ui/model/json/JSONModel', "sap/m/MessageToast"],
function(Controller, MessageToast, JSONModel) {
"use strict";
     
var Calendarcontroller = Controller.extend("timeTrackertimeTracker.controller.Calendarform", {
onInit: function() {

},

/* =========================================================== */
/* event handlers */
/* =========================================================== */

onSave: function() {
this.submitChanges({
success : function(oData) { 
// does not work without batch
console.log("submitChangesSuccess", oData);
},
error : function(oError) { // does not work without batch
console.log("submitChangesError", oError);
}
});
}, 
       
onCancel: function() {

this.resetChanges();
//this.getView().byId("addform").removeAllSelectedDates();
}
});
   
return Calendarcontroller;
   
});




and this is my View

<mvc:View
controllerName="timeTrackertimeTracker.controller.Calendarform"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:l="sap.ui.layout"
xmlns:forms="sap.ui.layout.form"
xmlns:me="sap.me">

<l:Grid defaultSpan="L12 M12 S12" width="auto">
<l:content>
<forms:SimpleForm
 editable="true" layout="ResponsiveGridLayout" labelSpanL="3" 
labelSpanM="3" labelSpanS="4" emptySpanL="0" emptySpanM="0" id="form"
emptySpanS="0" columnsL="2" columnsM="2">
<forms:content>
           
<Label text="Title"/>
<Input value="{title}"/>
           
<Label text="Description"
id="description"/>
<TextArea />
           
<Label text="Starttime"/>
<DateTimePicker
id="startime"
width="100%"
placeholder="Set Starttime"
/>
           
<Label text="Endtime"/>
<DateTimePicker
id="endtime"
width="100%"
placeholder="Set EndTime"
/>
           

</forms:content>
<Toolbar>
<ToolbarSpacer/>
<Button
text="{i18n>save}"
type="Accept"
id="save"
press="onSave"/>
<Button
text="{i18n>cancel}"
type="Reject"
id="cancel"
press="onCancel"/>
</Toolbar>
</forms:SimpleForm>

</l:content>
</l:Grid>
</mvc:View>


the Error in the console this.submitChanges is not a function

   Uncaught TypeError: this.submitChanges is not a function
at f.onSave (Calendarform.controller.js?eval:35)
at f.a.fireEvent (EventProvider-dbg.js:229)
at f.a.fireEvent (Element-dbg.js:593)
at f.firePress (ManagedObjectMetadata-dbg.js:426)
at f.B.ontap (eval at evalModuleStr (jquery.sap.global-dbg.js:3265), <anonymous>:760:179)
at f.a._handleEvent (Element-dbg.js:301)
at constructor.U._handleEvent (UIArea-dbg.js:786)
at HTMLBodyElement.dispatch (jquery-dbg.js:4737)
at g (jquery-mobile-custom-dbg.js:1972)
at HTMLBodyElement.p (jquery-mobile-custom-dbg.js:2050)


my manifest.json

{
"_version": "1.5.0",
"sap.app": {
"id": "timeTrackertimeTracker",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "ui5template.basicSAPUI5ApplicationProject",
"version": "1.40.12"
},
"dataSources": {
"appointments": {
"uri": "/",
"type": "OData",
"settings": {
"localUri": "localService/metadata.xml"
}
}
}
...........
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "timeTrackertimeTracker.i18n.i18n"
}
},
"appointments":{
"dataSource": "appointments",
"preload": true,
"settings": {
"defaultBindingMode": "TwoWay"
}
}
}


now how cann i include the submitChanges methode? and add Items correctly into the OData?

Accepted Solutions (0)

Answers (4)

Answers (4)

Former Member
0 Kudos

Hello everybody,

I have edited my code, but unfortunately it still does not work.

I have looked at the following document from sapui5 and Code from OpenSAPvideo.

https://sapui5.netweaver.ondemand.com/sdk/#docs/guide/6c47b2b39db9404582994070ec3d57a2.html

Code from OpenSap turorial Add.controller.js

		_onRouteMatched: function() {
			// register for metadata loaded events
			var oModel = this.getModel();
			oModel.metadataLoaded().then(this._onMetadataLoaded.bind(this));
		},
		
		_onMetadataLoaded: function () {
			// create default properties
			var oProperties = {
				ProductID: "" + parseInt(Math.random() * 1000000000),
				TypeCode: "PR",
				TaxTarifCode: 1,
				CurrencyCode: "EUR",
				MeasureUnit: "EA"
			};


			// create new entry in the model
			this._oContext = this.getModel().createEntry("/ProductSet", {
				properties: oProperties
			});


			// bind the view to the new entry
			this.getView().setBindingContext(this._oContext);


			
			// bind the view to the new entry
			//this.getView().setBindingContext(oContext);
		},

	_onCreateSuccess: function (oProduct) {
			// navigate to the new product's object view
			var sId = oProduct.ProductID;
			this.getRouter().navTo("object", {
				objectId : sId
			}, true);
	
			// unbind the view to not show this object again
			this.getView().unbindObject();
			
			// show success messge
			var sMessage = this.getResourceBundle().getText("newObjectCreated", [ oProduct.Name ]);
			MessageToast.show(sMessage, {
				closeOnBrowserNavigation : false
			});
		},

		/**
		 * Event handler for the save action
		 * @public
		 */
		onSave: function() {
			this.getModel().submitChanges();
		},


so this is my Calendarform.view.xml

<mvc:View
	controllerName="timeTrackertimeTracker.controller.Calendarform"
	xmlns="sap.m"
	xmlns:core="sap.ui.core"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:l="sap.ui.layout"
	xmlns:forms="sap.ui.layout.form"
	xmlns:me="sap.me">


    <l:Grid defaultSpan="L12 M12 S12" width="auto" class="gridNoMargin">
		<l:content>
			<forms:SimpleForm editable="true" layout="ResponsiveGridLayout" labelSpanL="3" labelSpanM="3" labelSpanS="4" emptySpanL="0" emptySpanM="0" id="form"
				emptySpanS="0" columnsL="2" columnsM="2">
				<forms:content>
					<Label text="ProjectNumber" />
					<Input value="{projectnumber}"
						id="projectnumber"
						placeholder="set a projectnumber"/>
					
					<Label text="Title"/>
					<Input value="{title}"
						id="title"
						placeholder="Set a Title"/>
					
					
					<Label text="Description"
					id="description"/>
					<TextArea value="{description}" 
						id="textarea"
						placeholder="Set your description"/>
					
					<Label text="Starttime"/>
					<DateTimePicker
					id="startime"
					value="{starttime}"
					width="100%"
					placeholder="Set Starttime"
					class="sapUiTinyMarginBottom" />
					
					<Label text="Endtime"/>
					<DateTimePicker
					id="endtime"
					value="{endtime}"
					width="100%"
					placeholder="Set EndTime"
					class="sapUiTinyMarginBottom" />
					
					<Label text="resttime"/>
					<Input type="Number"
						id="resttime"
						value="{resttime}"
						placeholder="please enter only a Number"/>
			    	<Toolbar>
						<ToolbarSpacer/>
						<Button
						text="{i18n>save}"
						type="Accept"
						id="save"
						press="onSave"/>
						<Button
						text="{i18n>cancel}"
						type="Reject"
						id="cancel"
						press="onCancel"/>
					</Toolbar>
				</forms:content>
			</forms:SimpleForm>
		</l:content>
    </l:Grid>
</mvc:View>

And this is my AppointmentsList.view.xml

<mvc:View
    	controllerName="timeTrackertimeTracker.controller.DateRange"
    	xmlns:l="sap.ui.layout"
    	xmlns:mvc="sap.ui.core.mvc"
    	xmlns="sap.m" >

        <Title  text="{i18n>appTitle}" titleStyle="Auto"  textAlign="Begin" visible="true"/>

    	<mvc:XMLView viewName="timeTrackertimeTracker.view.DateRange"/>
    	
					<Table
						id="listTracker"
						width="auto"
						items="{appointments>/appointments}"
						growing="true"
						growingScrollToLoad="true">
					<headerToolbar>
						<Toolbar>
							<Title id="tableHeader" text="Tracker Title"/>
						</Toolbar>
					</headerToolbar>
						<columns>
							<Column id="projecTitleColumn">
								<Text text="{i18n>trackerTitle}" id="projectTitleColumnText"/>
							</Column>
							<Column id="projecNumberColumn">
								<Text text="{i18n>projectnumber}" id="projectNumberColumnText"/>
							</Column>
							<Column
								id="startTimeColumn">
								<Text text="{i18n>startTime}"/>
							</Column>
							<Column
								id="endTimeColumn">
								<Text text="{i18n>endTime}"/>
							</Column>
							<Column
								id="restTime">
								<Text text="Rest Time"/>
							</Column>
							<Column
								id="durationColumn">
								<Text text="Duration"/>
							</Column>
							<Column
								id="flag">
								<Text text="Billable"/>
							</Column>
							<Column id="description" hAlign="End">
								<Text text="{i18n>description}" id="descriptionColumn"/>
							</Column>
							<Column id="actionColumn" hAlign="End">
								<Text text="{i18n>delete}" id="actionColumnTitle"/>
							</Column>
						</columns>


						<items>
							<ColumnListItem>
								<cells>
									<ObjectListItem
										title="{appointments>title}"/>
									<ObjectIdentifier
										title="{appointments>Id}"
										text="{appointments>projektnummer}"
										titleActive="true"
										titlePress="onShowDetailPopover"/>
									<Text text="{appointments>starttime}"/>
									<Text text="{appointments>endtime}"/>
									<ObjectIdentifier
										text="{appointments>rest}"
										/>
									<ObjectIdentifier
										text="{appointments>starttime} x {appointments>endtime}"
										/>
									<ObjectListItem
										markFlagged="{appointments>flag}"
										title="{appointments>flag}"
										/>
									<Text text="{appointments>description}"/>
									<Button id="delete" press="onDeleteProduct" icon="sap-icon://delete"/>
								</cells>
							</ColumnListItem>
						</items>
					</Table>
    </mvc:View>

the OData come from my MockServer.

first i have included the odata model in my Calendarform.controller.js

sap.ui.define(['sap/ui/core/mvc/Controller', 
	'timeTrackertimeTracker/controller/BaseController', 
	'sap/ui/model/json/JSONModel', 
	"sap/m/MessageToast",
	//"sap/ui/model/odata/ODataModel",
	"sap/ui/model/odata/v2/ODataModel"
	],

    	function(Controller, MessageToast, JSONModel, ODataModel) {
    	"use strict";
    	
    	//Global variables
    	var _oController, oModel, oView;
    	
 		//var starttimeVal, endtimeVal, oModel , textAreaVal;
    	var Calendarcontroller = Controller.extend("timeTrackertimeTracker.controller.Calendarform", {
    	
		/* =========================================================== */
		/* lifecycle methods                                           */
		/* =========================================================== */


    		
		onInit: function() {
				//Store controller reference to global variable
				_oController = this; 
				oView = this.getView();
		},
		
		/* =========================================================== */
		/* event handlers                                              */
		/* =========================================================== */


	onSave: function(oEvent) {

           var oProperties = {
				Id: "Id" + parseInt(Math.random() * 1000000000),
				projectnumber: "",
				//endtime - starttime in stunden ist duration
				duration: "",
				resttime: "",
				title: "",
				starttime: "",
				endtime: "",
				Description: ""
			};


			// create new entry in the model
			this._oContext = this.getView().getModel().createEntry("appointments>/appointments", {
				properties: oProperties,
				success: this._onCreateSuccess.bind(this)
			});


			// bind the view to the new entry
			this.getView().setBindingContext(this._oContext);


			this.getView().getModel().submitChanges();
			
			this.getView()._onCreateSuccess();


		}, 
		
		_onCreateSuccess: function (oAppointment) {
			// show success messge
			var sMessage = this.getResourceBundle().getText("newObjectCreated", [ oAppointment.Title ]);
			MessageToast.show(sMessage, {
				closeOnBrowserNavigation : false
			});
		},
    		
		onCancel: function() {
			this.getView().getModel().deleteCreatedEntry(this._oContext);
		}


    	});
     
    	return Calendarcontroller;
     
    });

and i changed my matadeta.xml

<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
	<edmx:DataServices m:DataServiceVersion="1.0" m:MaxDataServiceVersion="3.0"
					   xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
		<Schema Namespace="timeTrackertimeTracker" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
			<EntityType Name="appointments">
				<Key>
					<PropertyRef Name="Id"/>^
					<PropertyRef Name="projektnummer"/>
				</Key>
				<Property Name="Id" Type="Edm.String" Nullable="true" />
				<Property Name="projektnummer" Type="Edm.String" Nullable="true" />
				<Property Name="title" Type="Edm.String" Nullable="false" />
				<Property Name="starttime" Type="Edm.DateTime" Nullable="false" />
			    <Property Name="endtime" Type="Edm.DateTime" Nullable="false" />
			    <Property Name="duration" Type="Edm.Int16" MaxLength="2" Nullable="false" />
			    <Property Name="rest" Type="Edm.Byte" Precision="16" Scale="3" MaxLength="2" Nullable="false" />
			    <Property Name="flag" Type="Edm.Boolean" Nullable="false" />
				<Property Name="description" Type="Edm.String" Nullable="false"/>
			</EntityType>
		</Schema>
		<Schema Namespace="timeTrackertimeTracker.Model" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
			<EntityContainer Name="timeTrackertimeTrackerEntities" m:IsDefaultEntityContainer="true" p6:LazyLoadingEnabled="true"
							 xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
				<EntitySet Name="appointments" EntityType="timeTrackertimeTracker.appointments"/>
			</EntityContainer>
		</Schema>
	</edmx:DataServices>
</edmx:Edmx>

And in this BaseController.js is v2/ODataModel actually already imported.

I would like to add now a new entry through a form in my OData model. And the new entry should appear immediately in the Appointmentslist..

Now I try to add the new entry directly with "this" in ODATA

Manifest.json is configured tow-way.

What i want to do now is that, I must first assign the data from the form-element to a property or variable, then add this variable or property with createEntry to a new entry in oModel() in this Object.

My frist question: How can i get and set the content from the form, if the save button is clicked and onSave Event trigged ?

second: How can i set the date from the Form to the oModel.

And currently I have a problem. Although v2OModelData is already imported, but createEntry and deleteCreatedEntry is displaying the Error in the console

"Uncaught TypeError: Cannot read property 'createEntry' of undefined"

"Uncaught TypeError: Cannot read property 'deleteCreatedEntry' of undefined"

Is they any error with the import or call to the createEntry?

thanks very so much!!!

junwu
Active Contributor
0 Kudos

second, this is your controller, you have call submitchange from your model object.

former_member365727
Active Contributor
0 Kudos

Problem is with this .

this in your code for the event handler save() refers to current scope, meaning it refers to the method save() only and doesn't take the controller reference.

Use this approach instead...

Step 1: Store view controller reference globally so it can be accessed from any method. Implement the below code in onInit of controller

sap.ui.define(['sap/ui/core/mvc/Controller', 
'timeTrackertimeTracker/controller/BaseController', 
'sap/ui/model/json/JSONModel', "sap/m/MessageToast"],
function(Controller, MessageToast, JSONModel) {
"use strict";
     
   //Global variables
   var _oController;    //--> variable to store controller reference

var Calendarcontroller = Controller.extend("timeTrackertimeTracker.controller.Calendarform", {
onInit: function() {
    _oController = this;    //Store controller reference to global variable
}

Step 2: For the event handler replace this with _oController

onSave: function() {
  _oController.submitChanges({
     success : function(oData) { 
         // does not work without batch
         console.log("submitChangesSuccess", oData);
     },
     error : function(oError) { // does not work without batch
              console.log("submitChangesError", oError);
     }
  });
}
junwu
Active Contributor
0 Kudos

you have to use v2 odata model