I have an SAPUI5 app with 2 views. When I try navigate from the first view to the second view with an router it throws this error:
"Uncaught TypeError: JSONModel is not a constructor(…)"
The problem is I have to consume the content of the JSON to fill a table and with this error it is still empty
In a similar case/application my code runs without a problem, so I would be happy if someone can read my code if there are some errors...
Main.view.xml
<mvc:View controllerName="App.controller.Main" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
displayBlock="true" xmlns="sap.m">
<App>
<pages>
<Page>
<content>
<Table id="paramTable" items="{/callbackData}" width="auto" class="sapUiResponsiveMargin">
<columns>
<Column>
<Label text="Parameter"></Label>
</Column>
<Column width="10%">
<Label text="CurrentVal"></Label>
</Column>
<Column width="10%">
<Label text="TargetVal"></Label>
</Column>
<Column width="30%">
<Label text="Description"></Label>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier title="{key}"></ObjectIdentifier>
</cells>
<Text text="{currentVal}"></Text>
<Text text="{operator} {targetVal}"></Text>
</ColumnListItem>
</items>
</Table>
</content>
</Page>
</pages>
</App>
Main.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel"
], function(Controller , JSONModel) {
"use strict";
return Controller.extend("App.controller.Main", {
onInit : function() {
this.getView().setModel(new JSONModel({
callbackData: []
}));
},
setTableData : function() {
var here = this;
$.ajax({
url : '../../test.xsjs',
type : "GET",
success : function(data) {
here.getView().getModel().setProperty("/callbackData", data);
}
});
}
});
});
Thanks in advance!!!
var oModel = new JSONModel({
callbackData: []
});
this.getView().setModel(oModel);
Related
This question is a follow up to this: Button to add new row in SAPUI5 table
In my new scenario, I have added a "remove" button in the first column of the table. Again, the JSON file looks like this:
{
"Invoices": [
{
"ProductName": "Pineapple",
"Quantity": 21,
"ExtendedPrice": 87.2000,
"ShipperName": "Fun Inc.",
"ShippedDate": "2015-04-01T00:00:00",
"Status": "A"
},
...
]
}
My view now looks like this:
<mvc:View controllerName="stepbystep.demo.wt.controller.App" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:core="sap.ui.core"
xmlns:html="http://www.w3.org/1999/xhtml" displayBlock="true">
<Table id="ins" items="{ path : 'invoice>/Invoices', sorter : { path : 'ProductName' } }">
<headerToolbar>
<Toolbar>
<Button icon="sap-icon://add" text="Row" press="addRow"/>
<Button icon="sap-icon://display" text="Row" press="fetchRecords"/>
</Toolbar>
</headerToolbar>
<columns>
<Column width="50px"/>
<Column hAlign="Right" minScreenWidth="Small" demandPopin="true" width="4em">
<Text text="{i18n>columnQuantity}"/>
</Column>
<Column>
<Text text="{i18n>columnName}"/>
</Column>
<Column minScreenWidth="Small" demandPopin="true">
<Text text="{i18n>columnStatus}"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="false">
<Text text="{i18n>columnSupplier}"/>
</Column>
<Column hAlign="Right">
<Text text="{i18n>columnPrice}"/>
</Column>
</columns>
<items>
<ColumnListItem type="Navigation" press="onPress">
<cells>
<Button icon="sap-icon://delete" press="deleteRow" type="Reject"/>
<ObjectNumber number="{invoice>Quantity}" emphasized="false"/>
<ObjectIdentifier title="{invoice>ProductName}"/>
<Text text="{ path: 'invoice>Status', formatter: '.formatter.statusText' }"/>
<Text text="{invoice>ShipperName}"/>
<ObjectNumber
number="{ parts: [{path: 'invoice>ExtendedPrice'}, {path: 'view>/currency'}], type: 'sap.ui.model.type.Currency', formatOptions: { showMeasure: false } }"
unit="{view>/currency}" state="{= ${invoice>ExtendedPrice} > 50 ? 'Error' : 'Success' }"/>
</cells>
</ColumnListItem>
</items>
</Table>
And I have a function for adding a row (this one works fine):
addRow: function() {
this.getView().getModel("invoice").create("/Invoices", {
ProductName: "",
Quantity: "",
ShippedDate: "",
Status: ""
});
}
And I am trying to build one for deleting. This is what I have so far:
deleteRow: function(oArg) {
// var array = oArg.oSource.sId.split("-");
// var index = array[array.length - 1];
var path = oArg.oSource.oPropagatedProperties.oBindingContexts.invoice.sPath;
delete this.getView().getModel("invoice").oData[path.substr(1)];
this.getView().getModel("invoice").refresh(true);
}
But the row gets emptied and then returns again (like getting fetched from the mock server again). I am trying to completely remove the row (not just its contents), and the data to be removed.
I have seen plenty of examples online, but none cover my use case.
If you already use create for create new row then I think the best is to be consistent and use remove in order to remove it.
so in your case I think your code should look something like this:
this.getView().getModel("invoice").remove(path);
This line will do both:
Execute DELETE request to delete the object on the server (if you are using oDataModel)
Will delete the row from the table and refresh it because the table is bounded to this model
If you can please always use binding in your code. Using binding is much more efficient and easy to maintain because you don't need to deal with any DOM objects. The only thing that you need to do in code is creating/deleting/updating your model objects and UI5 runtime will do the rest for you.
If I have json data like this
[{"processor":"Mr. XYZ","components":["asd","efg","ghi","fjk"]} ,
{"processor":"Mr. XYZ","components":["asd","efg","ghi","ghi"]} ,
{"processor":"Mr. XYZ","components":["asd","efg","lkl"]} ]
If I am binding this to a table:
<Table id="myt1" items="{path: '/'}">
<columns>
<Column>
<Label text="Processor"/>
</Column>
<Column>
<Label text="Components"/>
</Column>
</columns>
<items>
<ColumnListItem>
<Text text="{processor}"/>
<Text text="{components}"/>
</ColumnListItem>
</items>
</Table>
How do I bind the array of components in separate lines in a cell for a processor in that table ?
Please refer the image for the output I am looking for.
Thanks in advance !
You could use a text formatter to add a new line after each array element.
<ColumnListItem>
<Text text="{processor}"/>
<Text text="{
path: 'components',
formatter: '.formatter.formatText'
}"/>
</ColumnListItem>
Formatter:
sap.ui.define([], function () {
"use strict";
return {
formatText : function(s){
var sOut = "";
s.forEach(function(sTxt){
sOut += sTxt + "\n";
});
return sOut;
}
}
});
How to bind data to using odata model? I'm getting error like Resource not found for the segment 'results'.
My code:
var url = "/sap/opu/odata/sap/ZODATA_SERVICE_NAME";
var oModel = new sap.ui.model.odata.ODataModel(url,false);
oModel.read("/EntityDataSet", null, null, true, function(oData) {
that.getView().setModel(oModel,"student");
},
function(error) {
});
<Table headerDesign="Standard"
items="{student>/results}"
id="table" >
<columns>
<Column >
<header>
<Label text="studentName" width="100%"/>
</header>
</Column>
<Column >
<header>
<Label text="studentRank" width="100%"/>
</header>
</Column>
</columns>
<items>
<ColumnListItem >
<cells>
text="{student>StudentName}"/>
text="{student>Rank}"/>
</cells>
</ColumnListItem>
</items>
</Table>
the ODataMOdel you are using is deprecated, make sure to use the v2.ODataModel instead
you don't need to execute an HTTP call via JavaScript (ODataModel.read(...) ) to get the data in order to bind it to the table.
I think you did not clearly understand OData and models in UI5. Having a look at the official SAPUI5 Tutorials might help you out.
Anyway, here is a running jsbin example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- use "sync" or change the code below if you have issues -->
<!-- XMLView -->
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc">
<Table
id="myTable"
growing="true"
growingThreshold="10"
growingScrollToLoad="true"
busyIndicatorDelay="0"
items="{/Customers('ALFKI')/Orders}">
<headerToolbar>
<Toolbar>
<Title text="Orders of ALFKI"/>
<ToolbarSpacer/>
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="OrderID"/>
</Column>
<Column>
<Text text="Order Date"/>
</Column>
<Column>
<Text text="To Name"/>
</Column>
<Column>
<Text text="Ship City"/>
</Column>
</columns>
<items>
<ColumnListItem type="Active">
<cells>
<ObjectIdentifier title="{OrderID}"/>
<Text
text="{
path:'OrderDate',
type:'sap.ui.model.type.Date',
formatOptions: {
style: 'medium',
strictParsing: true
}
}"/>
<Text text="{ShipName}"/>
<Text text="{ShipCity}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
//### Controller ###
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/odata/v2/ODataModel"
], function (Controller, ODataModel) {
"use strict";
return Controller.extend("MyController", {
onInit : function () {
// in component based apps you would not
// even need this piece of code:
this.getView().setModel(
new ODataModel("https://cors-anywhere.herokuapp.com/services.odata.org/V2/Northwind/Northwind.svc/", {
json : true,
useBatch : false
})
);
}
});
});
//### THE APP: place the XMLView somewhere into DOM ###
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
try changing
that.getView().setModel(oModel,"student");
to
this.getView().setModel(oModel,"student");
that.getView().setModel(oModel,"student"); //incorrect
this.getView().setModel(oModel,"student"); //refers to this particular controller
Im building an application with two textboxes, a button and a table. On pressing the button, an array of filters is composed from the contents of the textboxes and sent to my oData service in a read request. Right now, when one record is returned (as it shows in the console), the table will not be updated. What am I missing?
This is the table:
<Table id="PLTab" items="{/ORDSET}">
<headerToolbar>
<Toolbar>
<Title text="Planned Orders" level="H2" />
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="Product" />
</Column>
<Column>
<Text text="Planned Order" />
</Column>
<Column>
<Text text="Production Planner" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier title="{Maktx}" text="{Matnr}" />
<Text text="{Ordno}" />
<Text text="{Name}" />
</cells>
</ColumnListItem>
</items>
</Table>
And this is the relevant part of the controller:
onInit: function() {
var oModel = this.getOwnerComponent().getModel("path");
oModel.refresh(true);
this.getView().setModel(oModel);
},
openOrders: function(oEvent) {
var PLFilters = [];
PLFilters.push(new sap.ui.model.Filter({
path: "Matnr",
operator: sap.ui.model.FilterOperator.EQ,
value1: this.getView().byId("Product").getValue()
}));
PLFilters.push(new sap.ui.model.Filter({
path: "Locno",
operator: sap.ui.model.FilterOperator.EQ,
value1: this.getView().byId("Location").getValue()
}));
var oModel = this.getOwnerComponent().getModel("path");
oModel.read("/ORDSET", {
filters: PLFilters,
success: function(oData, oResponse) {
console.log(oData);
}
});
}
Thanks & regards,
Max
var oModel = this.getOwnerComponent().getModel("path");
You use the model named "path" to read data, but in your XML View you use the default model (unnamed).
Try to change to
var oModel = this.getOwnerComponent().getModel();
View1.view.xml
<mvc:View xmlns:f="sap.ui.layout.form" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="Login.controller.View1">
<App>
<pages>
<Page title="Login">
<f:SimpleForm maxContainerCols="2" editable="true" layout="ResponsiveGridLayout" labelSpanL="4" labelSpanM="4" emptySpanL="0" emptySpanM="0" columnsL="2" columnsM="2">
<f:content>
<Input width="100%" id="__input0" placeholder="UserID" liveChange="true" />
<Input width="100%" id="__input1" type="Password" placeholder="Password" />
<Button text="Login" width="100px" id="__button0" type="Accept" press="Validation" />
</f:content>
</f:SimpleForm>
<Table items="{ path: '/Item' }" id="tableID" width="90%">
<items>
<ColumnListItem counter="0" id="__item0">
<cells>
<Text id="a1" text="{OrderID}" />
<Text text="{Quantity}" />
</cells>
</ColumnListItem>
</items>
<columns>
<Column id="__column0">
<header>
<Label text="OrderID" id="__label0" />
</header>
</Column>
<Column id="__column1">
<header>
<Label text="Quantity" id="__label1" />
</header>
</Column>
</columns>
</Table>
<content/>
</Page>
</pages>
</App>
</mvc:View>
view1.controller.js
sap.ui.define(["sap/m/MessageToast",
"sap/ui/core/mvc/Controller", 'sap/ui/model/json/JSONModel'
], function(MessageToast, Controller, JSONModel) {
"use strict";
return Controller.extend("Login.controller.View1", {
onInit: function(oEvent) {
// set explored app's demo model on this sample
var oModel = new JSONModel(jQuery.sap.getModulePath("Login", "/model/Products.json"));
sap.ui.getCore().setModel(oModel);
this.getView().byId("tableID").setModel(oModel);
// this.getView().byId("samplepie").setModel(oModel);
},
Validation: function() {
var UserID = this.getView().byId("__input0").getValue();
var Password = this.getView().byId("__input1").getValue();
if (UserID == "") {
MessageToast.show("Please Enter UserID");
return false;
} else if (Password == "") {
MessageToast.show("Please Enter Password");
return false;
} else if (UserID == sap.ui.getCore().byId("a1").getValue()) {
MessageToast.show("authenticated ");
}
}
});
});
products.json
{
"Item": [{
"OrderID": "1100M",
"Quantity": 100
}, {
"OrderID": "11001I",
"Quantity": 250
},
{
"OrderID": "11002D",
"Quantity": 400
}
]
}
I have tried this code for login along with authentication but am getting error as getValue not defined when i used to fetch JSON values from view to controller,can anyone please give a solution?