Bonita 7 : Custom Widget property type to support JSON data - business-process-management

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

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.
});

How to create an OData service for SAPUI5 TreeTable?

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.

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.

Cascading Dropdowns Using Knockout.js

I'm able to get this working except for two things that I just can't figure out:
Problem 1: I need to get both of the following but right now can only achieve one OR the other:
Select options need to have value and text
The selectedOption captured in the model needs to return the object of the selected option and not just the value of the option
I can affect which one of these works by including or excluding the following from my select markup:
...data-bind="optionsValue = 'Id'"...
How can I achieve both?
Problem 2: I need to set the selected option in the dropdown to an object I retrieve from a cookie containing the user's preferred value. My below implementation does not succeed in setting the selected value at all. What am I missing?
$(document).ready(function(){
var userOption = $.cookie("userPref") == null ? undefined : JSON.parse($.cookie("userPref"));
var model = function(){
this.options = ko.observableArray();
this.childOptions = ko.observableArray();
this.selectedOption = ko.observable(userOption); //this does nothing to set the value
this.selectedOption(userOption); //this also does nothing
this.options.subscribe(function(){
//this.selectedOption() returns an object if optionsValue is excluded from select databinding and returns option value if included
$.cookie("userPref", JSON.stringify(this.selectedOption());
this.childOptions(undefined);
this.childOptions(this.selectedOption() ? this.selectedOption().children : []);
}.bind(this));
};
var viewModel = new model();
ko.applyBindings(viewModel);
$.ajax({
type: "GET",
url: "myurl",
success: function(data){
viewModel.options(data);
}
});
});
<select data-bind="options: options, optionsText: 'text', optionsValue: 'Id', value: selectedOption, optionsCaption: 'Select Option'"></select>
You can't use the entire object as the value because an option value must be a simple type: string, int, etc. I suppose you could JSON encode the object (so it's a string) and set the value to that, but then you'd have to reciprocate on the backend and decode the posted string value back into an object and somehow work with that. However, said object would be disconnected from EF, so you'd have to fetch the object new from the database anyways in order to do anything meaningful with it. And, your second problem is the same as your first, you can't use a full object.
The way this is usually done is with ids. You make the option value the object's id. Then, you can set the selected option based on the object's id from the cookie. When you get to the backend, if you need to work with the object, you fetch it by the posted id. Anything else is not really a tenable situation.

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