Skip to Content
avatar image
Former Member

SAPUI5 Add new item to odata with a form

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?

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

4 Answers

  • Mar 06, 2017 at 04:22 PM

    you have to use v2 odata model

    Add comment
    10|10000 characters needed characters exceeded

  • Mar 06, 2017 at 05:01 PM

    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);
         }
      });
    }
    Add comment
    10|10000 characters needed characters exceeded

  • Mar 06, 2017 at 06:22 PM

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

    Add comment
    10|10000 characters needed characters exceeded

  • avatar image
    Former Member
    Mar 15, 2017 at 02:14 PM

    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!!!

    Add comment
    10|10000 characters needed characters exceeded