How to create an OData service for SAPUI5 TreeTable? - odata

Does someone know if there is a way to create a OData Service that is bindable to an SAPUI5 TreeTable element?
According to the example from here:
https://sapui5.netweaver.ondemand.com/sdk/#test-resources/sap/ui/table/demokit/TreeTable.html
The recursive structure of the data is a list. For example:
//Define some sample data
var oData = {
root:{
name: "root",
description: "root description",
checked: false,
0: {
name: "item1",
description: "item1 description",
checked: true,
...
I expected to solve that problem with an navigation at the service side. Like
Element with attributes and one attribute points to a list of Elements.
But this would not be the same.
I also detected this thread, but the answer is one year old:
http://scn.sap.com/thread/3389546
All in all, is the answer still true? Or is there a solution, so that the data binding works?

You can use treebinding from ODataModel. First of all, prepare backend. You need to cycle navigation in your entity set. For example, you have entity set ItemCollection and you add navigation property ItemNavigation which refers to ItemCollection. After just bind tree to your TreeTable:
var oTreeTable = this.getView().byId("myTreeTable");
oTreeTable.bindRows({
path : '/ItemCollection',
properties : {
navigation : {
'ItemCollection' : 'ItemNagigation'
}
}
});
Should work fine but be aware to use it with Tree control. TreeTable loads navigation item by click on its parent and Tree loads the whole tree at once.

Related

Is there alternative available to jqx render capability - $gridContainer.jqxGrid('render')

We are using jqxGrid library from jqwidgets. In this I am using jqxDropDownList for displaying list created from json data and upon selecting a value from dropdown filtering should happen.
We had some UI issues hence we had to remove below line, now I would like to know is there alternative available for below code :
code :
$gridContainer.jqxGrid('render')
if you want to update two-way data then you should used observableArray()
here check the demo code jqx observable array
var observableArray = new $.jqx.observableArray(
[{name: "Andrew Smith"},
{name: "Gordon Brown"}],
function(changes)
{
// handle changes here.
});

Bonita 7 : Custom Widget property type to support JSON data

I am trying to create a new custom widget in Bonita 7 and I need a Property that can accept JSON data (not simple array collection) i.e., I want to assign below data
[
{
'header1': 'data1-1',
'header2': 'data1-2',
'header3': 'data1-3'
},
{
'header1': 'data2-1',
'header2': 'data2-2',
'header3': 'data2-3'
}
]
I tried all the available property types (text,choice ,html ,integer,boolean ,collection property) & I guess nothing works.
Could someone help me to achieve this.
I am trying to create a Smart-Table custom widget (https://github.com/lorenzofox3/Smart-Table) & I want the table data(rows) to be populated using a variable that is of JSON type.
Is there any other way of achieving this.
Thank you very much for your time
I am very sorry, collection property type actually works
This is what I did:
In the CUSTOM WIDGET EDITOR
1A) created a new property :
name : tableDataCollection
Label: TABLE_DATA
Type: collection (text type also works)
Default value: (trying to assign JSON data here didn't work for me)
1B) In the Controller box, use the property tableDataCollection defined in step 1A:
$scope.data = $scope.properties.tableDataCollection; (inside function ($scope) {})
1C) In the Template box, use the variable data defined in step 1B:
example : <tr ng-repeat="row in data">
2) In the PAGE EDITOR (FORM EDITOR), if you are using the custom widget created in step 1, you will see a new fields on the right related to your custom widget. In my case it is TABLE_DATA
2A) Now, create a new form variable of type JSON.
example : data2Var =
[{
"header1": "data1-1",
"header2": "data1-2",
"header3": "data1-3"
},
{
"header1": "data2-1",
"header2": "data2-2",
"header3": "data2-3"
}]
2B) Now, Assign the variable created in step 2A to your custom widget field.
in my case, I assigned data2Var to TABLE_DATA

bindProperty to Single OData Entity

In UI5, is it possible to bind a single attribute of a single entity to a control property if your model is an OData? Binding works ok if you bind an aggregation to an entity set but does not seem to work with properties to entities. Say I have an entity set called TestSet. Each "Test" has attribute Key and Name. I'd like to bind the title of a table to the Name of one of the entities on that set.
What's wrong with the following code?
createContent: function(oController) {
jQuery.sap.require("sap.ui.table.Table");
var oTable = new sap.ui.table.Table({title: "{/TestSet('01')/Name}"});
oTable.setModel(new sap.ui.model.odata.ODataModel("/path/to/root/of/odata/"));
oTable.bindProperty("title", "/TestSet('01')/Name");
return oTable;
},
OData works ok when tested in isolation. /TestSet returns set of Test entities and /TestSet('01') returns one of those entities.
I've tested binding to /Name, /TestSet('01')/Name, etc. Nothing seems to work.
You can effect a property binding like this by binding the control to the specific element (hierarchy, as it were, is aggregation->element->property). So taking your example, you could do this:
var oTable = new sap.ui.table.Table({
title : "{Name}"
});
and then when you do this:
oTable.bindElement("/Products(0)");
the HTTP call is made by the OData model mechanism and the value appears in the table's title property.
Here's a running example, using Northwind.
According to the developer guide ...
Requests to the back end are triggered by list bindings, element bindings, and CRUD functions provided by the ODataModel. Property bindings do not trigger requests.
Thus, instead of trying to bind data directly on the properties of the target control with an absolute path, leverage ContextBinding (aka. "Element Binding") on the parent control or on the target control itself, and then bind the data on the properties of the target control or even further on child controls with a relative path (> instead of >/ in the path).
We can bind a single entity either in JS (e.g. if entity keys are required) or in XML views.
In JS
Instead of hardcoding the key predicate of the entity type, make sure to create the binding path together with key(s) via v2.ODataModel.createKey() dynamically after $metadata is loaded.
const oTable = new Table({ // Required from "sap/ui/table/Table"
title: "{Name}", // No absolute but relative binding path (no '/')
});
const myODataModel = /*...*/;
await myODataModel.metadataLoaded();
const bindingPath = myODataModel.createKey("/TestSet", { // See stackoverflow/a/47016070
key1: "...",
key2: 1234,
}); // Returns e.g. "/TestSet(key1='test1',key2='1234l')"
oTable.bindElement({ // Triggers a request and resolves the relative {Name} property.
path: bindingPath,
parameters: {
expand: "...",
select: "...",
// ... for more options see sap/ui/model/odata/v2/ODataContextBinding
},
events: { // Event handlers can be also assigned
dataRequested: e => { /*...*/ },
dataReceived: e => { /*...*/ },
change: e => { /*...*/ },
},
});
Note: bindElement and bindObject are same APIs just with different names. See also GitHub issue#3000.
In XML views
In XML views, single object / entity can be bound via binding in any controls. But creating keys dynamically (with createKey as shown above) is not possible. Hence, use binding only in combination with a <NavigationProperty> name, where keys are not required to be defined.
<table:Table xmlns:table="sap.ui.table"
binding="{
path: 'ToThatSingleEntity',
parameters: {
expand: '...',
select: '...'
},
events: {
dataRequested: '.onDataRequested',
dataReceived: '.onDataReceived',
change: '.onDataFromModelChanged'
}
}"
title="{FromThatSingleEntity}">
binding="{/TestSet(<keys>)}" is also possible but, again, the keys need to be then hardcoded.

Breeze navigation property is not observable

I don't understand something about collection navigation properties.
First, I went through metadata debug, all checks out. As per documentation, I expected the navigation collection property to be observable, e.g. I can get the collection via
Foo.Bar() // bar is KO observable array
However, I can't get it working like that.
My query:
new breeze.EntityQuery()
.from('Classes')
.where('ClassId', '==', id)
.expand('LessonOfClasses')
Results to:
[
{
"$id":"1",
"$type":"Model.Class, Model",
"ClassId":24,
"LessonOfClasses":[
{
"$id":"2",
"$type":"Model.LessonOfClass, Model",
"class_lesson_id":30,
"class_id":24,
"lesson_id":40,
"Class":{
"$ref":"1"
},
"Lesson":null
},
// other instances of LessonOfClass...
]
// other properties of Class...
}
[
Which looks fine to me. However, when I run the query the result is:
var classObject = data.results[0];
classObject.LessonOfClasses // returns normal array
classObject.LessonOfClasses() // error: not a function
Figured out when knockout isn't available as a dependency, Breeze results to using plain JSON objects.
The problem is I'm using knockout as a require.js dependency and the global ko reference wasn't set.
requirejs(['knockout'], function(ko) {
window.ko = ko;
})
Breeze is looking strictly for ko, as opposed to durandal which I think looks for knockout.

How do I bind the column with the property?

I'm trying connect slickgrid and breeze.js, but I got a problem.
breeze generates the js model for you, and the object properties has get and set methods like:
var p1 = myobj.property1();
var p2 = myobj.property2();
myobj.property1("Test");
But in the slickgrid columns model, how do I bind the column with the property?
columns : [
{
id: "id",
name: "ID",
field: "property1" //this way I only see for every row on the page the text "function..."
},
{
id: "prop2", name: "prop2", field: "property2"
}
]
Try using the breeze "backingStore" adapter instead of the default "ko" (knockout) adapter.
This requires just a single line of Breeze configuration near the top of the file
breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);
The backingStore adapter creates ES5 props for your model instead of "knockout" properties. I guessing that these will be easier for slickgrid to bind to.

Resources