How to filter/sort OpenUI5 Grid by column, which is nested in the json? - filter

I'm now testing the capabilities of this grid and I'm having a look at this example at the moment.
Last week, I tried some basic loading of data, returned from the controller of the MVC app that I'm working on. It returns json, which I then give to the grid to be displayed.
The data, that I want to show, is stored in multiple tables. For now, I load data from only two of them for simplicity, because I'm only testing the capabilities of the grid - will it suit our needs.
The data, which arrives at the grid (in js), looks something like this:
{
Cars: [
{
car_Number: '123',
car_Color: 'red',
car_Owner: Owner: {
owner_ID: '234',
owner_Name: 'John'
},
car_DateBought: '/Date(1450648800000)/'
},
{
car_Number: '456',
car_Color: 'yellow',
car_Owner: Owner: {
owner_ID: '345',
owner_Name: 'Peter'
},
car_DateBought: '/Date(1450648800000)/'
},
{
car_Number: '789',
car_Color: 'green',
car_Owner: Owner: {
owner_ID: '567',
owner_Name: 'Michael'
},
car_DateBought: '/Date(1450648800000)/'
}
]
}
Here is some sample code of what I have done so far:
$.ajax({
type: 'post',
url: BASE_HREF + 'OpenUI5/GetAllCars',
success: function (result) {
var dataForGrid = result['rows'];
debugger;
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(dataForGrid);
var oTable = new sap.ui.table.Table({
selectionMode: sap.ui.table.SelectionMode.Multi,
selectionBehavior: sap.ui.table.SelectionBehavior.Row,
visibleRowCountMode: sap.ui.table.VisibleRowCountMode.Auto,
minAutoRowCount: 10,
//visibleRowCount: 10,
showNoData: false
});
// define the Table columns and the binding values
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({
text: "ID of car"
}),
template: new sap.ui.commons.TextView({ text: "{car_Number}" }),
sortProperty: "car_Number", // https://sapui5.netweaver.ondemand.com/sdk/test-resources/sap/ui/table/demokit/Table.html#__2
filterProperty: "car_Number"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Color of car" }),
template: new sap.ui.commons.TextView({ text: "{car_Color}" }),
sortProperty: "car_Color",
filterProperty: "car_Color"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Car Owner ID" }),
template: new sap.ui.commons.TextView({
// does not work like this -> text: "{Owner.owner_ID}"
text: {
path: 'Owner',
formatter: function (owner) {
return owner !== null ? owner['owner_ID'] : '';
}
}
}),
sortProperty: "Owner.owner_ID", // these two don't work
filterProperty: "Owner.owner_ID"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Car Owner Name" }),
template: new sap.ui.commons.TextView({
// does not work like this -> text: "{Owner.owner_Name}"
text: {
path: 'Owner',
formatter: function (owner) {
return owner !== null ? owner['Name'] : '';
}
}
}),
sortProperty: "Owner.owner_Name", // these two don't work
filterProperty: "Owner.owner_Name"
}));
var dateType = new sap.ui.model.type.Date({ // http://stackoverflow.com/questions/22765286/how-to-use-a-table-column-filter-with-formatted-columns
pattern: "dd-MM-yyyy"
});
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Date bought" }),
template: new sap.ui.commons.TextView({
text: {
path: 'car_DateBought',
formatter: dateFormatterBG
}
}),
sortProperty: "car_DateBought",
filterProperty: "car_DateBought",
filterType: dateType
}));
oTable.setModel(oModel);
oTable.bindRows("/");
oTable.placeAt("testTable", "only");
},
error: function (xhr, status, errorThrown) {
console.log("XHR:");
console.log(xhr);
console.log("Status:");
console.log(status);
console.log("ErrorThrown:");
console.log(errorThrown);
}
});
My problems:
I cannot sort or filter the list of cars by owner_ID or owner_Name. How should I do the filtering and sorting? Should it be done with the help of a formatter function in some way, or...?
I can sort by car_DateBought, but I cannot filter the cars by this field. First, I tried setting filterType: dateType, then I tried setting it to filterType: dateFormatterBG(it turns out, that dateType does exactly the same thing as my own dateFormatterBG does, btw).
function dateFormatterBG(cellvalue, options, rowObject) {
var formatedDate = '';
if ((cellvalue != undefined)) {
var date = new Date(parseInt(cellvalue.substr(6)));
var month = '' + (date.getMonth() + 1);
var day = '' + date.getDate();
var year = date.getFullYear();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
formatedDate = [day, month, year].join('-');
}
return formatedDate;
}
Anyway, as I said, I tried both, but it doesn't work. When I click on the header of a column like in the example in the first link, I don't get any sort of a datepicker. How can I tell OpenUI5, that this column needs to be filtered by date and it should provide the user with a datepicker, when he/she clicks on the 'Filter' input field at the bottom of the dropdown menu? When I try to write the date in the filter field like '07-11-2016' (the way it is formatted), I get an empty table/grid. If I try to enter the huge number from field car_DateBought in the json object, all available rows in the table stay the same and when I reclick on the header, the filter field at the bottom of the dropdown menu appears with error-state.
Thank you in advance for your help and pieces of advice!
Edit:
This is just sample, dummy data. I try to load the real data and I see, that in the table I've got a couple of rows with date, which is today (07-11-2016, or 11/7/2016 if you prefer). That's why getting an empty table after trying to filter means it's not working correctly.

Sorting: in a sample I am looking at the following appears in the controller:
onInit : function () {
this._IDSorter = new sap.ui.model.Sorter("my_id", false);
},
....
Then in the view there is a button defined in the header column as
<Column>
<Label text="Project"/>
<Button icon="sap-icon://sort" press="onSortID" />
</Column>
And back in the controller there is a further function:
onSortID: function(){
this._IDSorter.bDescending = !this._IDSorter.bDescending;
this.byId("table").getBinding("items").sort(this._IDSorter);
},
I read this collectively as defining a sorter in the onInit(), then toggle/reversing it in the click event of the sort button in the column header via the onSortId() function. The OpenUI5 API doc re sorters indicates there are more parameters in the sorter constructor for initial sort direction and sorting function.
Following this pattern, for your needs to sort on the owner_ID or owner_Name, I assume you could set up a sorter as
this._OwnerIDSorter = new sap.ui.model.Sorter("car_Owner/owner_ID", false);
this._OwnerNameSorter = new sap.ui.model.Sorter("car_Owner/owner_Name", false);

Related

How to load and save a work order record using the map reduce script

I am trying to only load and save a work order record using the map-reduce script. But I don't see logs for loaded work orders or saved work orders. the script is executing only until work_order_Id. Please Help!   
Below is my code...
function getInputData(){
var process_data =[];
try{
var workorderSearchObj = search.create({
type: "workorder",
filters:
[
["type","anyof","WorkOrd"],
"AND",
["mainline","is","T"],
"AND",
["status","anyof","WorkOrd:A","WorkOrd:B","WorkOrd:D"]
],
columns:
[
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({name: "tranid", label: "Document Number"})
]
});
var searchResultCount = workorderSearchObj.runPaged().count;
log.debug("workorderSearchObj result count",searchResultCount);
workorderSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
var work_Order = result.getValue({name:'internalid'});
var document_no = result.getValue({name:'tranid'});
process_data.push({
'work_Order':work_Order,
'document_no':document_no
});
return true;
});
}catch(error){
log.debug(error);
}
return process_data;
}
function map(context){
var process_data=JSON.parse(context.value);
log.debug('process_data',process_data);
var work_order_Id = process_data.work_Order;
log.debug("work_order_Id",work_order_Id);
var work_Order_obj = record.load({
type: record.Type.WORK_ORDER,
id: work_order_Id,
isDynamic: true
});
log.debug("work_Order_obj",work_Order_obj);
var recId=work_Order_obj.save({
enableSourcing: true,
ignoreMandatoryFields: true
});
log.debug("recId",recId);
}
I am trying to load and save work order record. But its not executing.I am trying to load and save a work order record. but it's not loading.
I usually like to simply return saved searches in getInputData because it's consistent to work with and you don't have to fuss with the going over 4k search results and having to return arrays of objects that you put together yourself. Usually transforming data to be in the format you want is best done in the map stage.
/**
* #NScriptType MapReduceScript
* #NApiVersion 2.x
*/
define(["N/search", "N/record"], function (search, record) {
function getInputData() {
// run a saved search of work orders
return search.create({
type: "workorder",
filters: [
["type","anyof","WorkOrd"],
"AND",
["mainline","is","T"],
"AND",
["status","anyof","WorkOrd:A","WorkOrd:B","WorkOrd:D"]
],
columns: [
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({name: "tranid", label: "Document Number"}),
]
});
}
function map(context) {
// get the work order id
var workOrderId = JSON.parse(context.value).id;
log.debug("workOrderId", workOrderId);
// load the work order
var wordOrderRecord = record.load({
type: record.Type.WORK_ORDER,
id: work_order_Id,
isDynamic: true,
});
log.debug("wordOrderRecord", wordOrderRecord);
// save the work order
var recId = wordOrderRecord.save({
enableSourcing: true,
ignoreMandatoryFields: true
});
log.debug("recId",recId);
}
function summarize(context) {
// log any errors that might occur
context.mapSummary.errors.iterator().each(function (_, errJson) {
var error = JSON.parse(errJson);
log.error({title: error.name, details: error.message});
return true;
});
}
return {
getInputData: getInputData,
map: map,
summarize: summarize,
};
})

Kendo Chart Does not show Data

Im sending my json data through controller like following:i have written the query here just to prevent making it complicated and messy :
My Controller Returning This:
public JsonResult powerConverter(string regionalManager)
foreach (DataRow dt in dt_power_conv.Rows)
{
_powerConv.turbineName.Add(dt["turbine_name"].ToString());
_powerConv.duration_hrs.Add(double.Parse(dt["duration_hrs"].ToString()));
_powerConv.abb_conv.Add(dt["abb_conv"].ToString());
_powerConv.eei_conv.Add(dt["eei_conv"].ToString());
_powerConv.leit_drive_conv.Add(dt["leit_drive_conv"].ToString());
}
return Json(_powerConv, JsonRequestBehavior.AllowGet);
}
in my view I get it with an Ajax call and simply bind my chart with it:
$.ajax({
dataType: "json",
type: "POST",
url: "#Url.Action("powerConverter","Ranking")",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ "regionalManager": tmpString }),
success: function (result) {
debugger;
$("#powerChart").kendoChart({
dataSource: {
data: result
},
chartArea: {
background: "#fcfcfc",
},
series: [{
axis: "l100km",
type: "column",
// name: "DURATION",
color: "#008080",
field: "duration_hrs",
categoryField: "turbineName"
},
],
categoryAxis: {
axisCrossingValue: [0, 20],
majorGridLines: {
visible: false
},
line: {
visible: true
},
labels: {
rotation: 340
},
},
tooltip: {
visible: true,
// majorUnit:10,
template: " #= value #"
},
});
}
});
I also posted the screen shot of my json,but still its not working,i set the categoryField and field with the exact name im getting from json but the chart shows nothing
It looks like the controller is returning two arrays, one for errorDuration and one for turbineName. Try changing the controller to return an array of objects.
You would want a review of returned json to show
[0] = { duration: 1, turbine: "a" }
[1] = { duration: 2, turbine: "b" }
[2] = { duration: 3, turbine: "c" }
In the chart the config settings for the series the field names have to match exactly the property names of the data elements, thus
field: "duration",
categoryField: "turbine",
Added
The controller code appears to be populating a list of a model class whose fields are also lists. Try updating it to return the Json for a list of objects
For quickness this example shows how using anonymous objects. Strongly typed objects are highly recommended for robustness and Visual Studio intellisense. The field names that you use in your kendo chart configuration will be "turbine_name" and "duration_hours"
// This technique copied from #Paul Rouleau answer to
// https://stackoverflow.com/questions/612689/a-generic-list-of-anonymous-class
// initialize an empty list that will contain objects having two fields
var dataForJson = new List<Tuple<string, double>>()
.Select(t => new {
turbine_name = t.Item1,
duration_hours = t.Item2 }
).ToList();
// go through data table and move data into the list
foreach (DataRow row in myDataTable.Rows)
{
dataForJson.Add (new {
turbine_name = (string)row["turbine_name"],
duration_hours = (double)row["duration_hours"]
});
}
return Json(dataForJson, JsonRequestBehavior.AllowGet);
Note, if you do further research you will find numerous other ways to convert a data table into a Json

meteor fullcalendar not reacting to events at all

I use drblue:fullcalendar. Display works fine but I cannot get any kind of event to work. I have tried different ones. In the following code snippet I have tried the loading event:
Template.Schedule.helpers({
calendarOptions: {
// Standard fullcalendar options
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
slotDuration: '01:00:00',
minTime: '07:00:00',
maxTime: '22:00:00',
lang: 'en',
defaultView: 'agendaWeek',
contentHeight: 500,
firstDay: 1,
timeFormat: 'HH:mm',
timezone: 'UTC',
selectable: true,
// Function providing events reactive computation for fullcalendar plugin
events: function(start, end, timezone, callback){
var events = [];
Assignments.find().map(function(doc){
var startTimeHours = Number(doc.time.substr(0, 2));
var startTimeMinutes = Number(doc.time.substr(3, 2));
var startDateTime = new Date(doc.date);
startDateTime.setHours(startDateTime.getHours() + startTimeHours);
startDateTime.setMinutes(startDateTime.getMinutes() + startTimeMinutes);
var endDateTime = new Date(doc.date);
var effort = doc.state == 'finished' ? doc.realEffort : doc.effort;
endDateTime.setHours(startDateTime.getHours() + effort);
endDateTime.setMinutes(startDateTime.getMinutes());
var getColorForState = function(state)
{
switch(state)
{
case 'finished': return '#00bb00';
}
return '#1197C1';
};
var getBorderColorForState = function(state)
{
switch(state)
{
case 'finished': return '#009900';
}
return '#004781';
};
return{
id: doc.title,
start: startDateTime,
end: endDateTime,
title: doc.title,
backgroundColor: getColorForState(doc.state),
borderColor: getBorderColorForState(doc.state)
}
}).forEach(function(event){
events.push(event);
});
callback(events);
},
// Optional: id of the calendar
id: "calendar1",
// Optional: Additional classes to apply to the calendar
addedClasses: "col-md-12"
// Optional: Additional functions to apply after each reactive events computation
}
});
Template.Schedule.events({
loading: function(isLoading, view){
console.log('hi');
}
});
No JS error on client or server and no log entry, either. I have also tried dayClick, select and clickEvent but I do not get any log entry. If I put an alert into it I also do not receive anything.
Not sure why downvoted, if you need more information or details, please provide it.
Anyways, I was able to solve it. There was some "wrong" code out there and I did not find any example, but it works when I just add the corresponding event to the options, i.e.:
Template.Schedule.helpers({
calendarOptions: {
// all the various options
eventClick: function(event, jsEvent, view){
alert(event.title + "\r\n\r\n" + event.description);
},

Client-side Generated KendoUI Grid is not highlighting selected row when grid is redisplayed

Client-side Generated KendoUI Grid is not highlighting selected row when grid is redisplayed (Kendo UI Complete v2013.1.514).
Kendoui grid is in a KendoUI Tab (Tab #1). Clicking on the 3rd row highlights the row. Clicking on the second tab (Tab #2) hides the grid tab and shows another grid. When clicking back on Tab #1 the first grid is redisplayed and the contents are shown.
When stepping through the tab onActivate(arg) function I can see using grid.select() that the row that was last selected is still the selected row however the row isn't highlighted.
I tried the following code in an attempt to reselect the row:
var element = $(WORK_PRODUCT),
grid = element.data("kendoGrid"),
row = element.find("tbody>tr[data-uid='" + grid.dataSource.get(_selectedWorkProduct).uid + "']");
grid.select(row);
I also examined the inner and outer HTML and the selected row matches exactly what was selected the first time the row was selected (TR class=k-state-selected role=row aria-selected=true data-uid="119b95c7-f3e4-4160-821e-507fbdc70026">7964
How can I visibly show that the row is selected? Thanks in advance!
Below is the code that initializes the grid:
DashViewUI.prototype.initWorkProducts = function (arg) {
$(WORK_PRODUCT).kendoGrid({
filterable: true
, sortable: true
, selectable: "row"
, pageable: true
, ajax: true
, columns:
[
{
field: "ID"
, title: ""
, sortable: true
, hidden: true
}
, {
field: "Number"
, title: "Case No."
, width: 80
, sortable: true
, filterable: true
}
, {
field: "Name"
, title: "Case Name"
, width: 120
, sortable: true
}
, {
field: "Status"
, title: "Status"
, width: 70
, sortable: true
}
]
, dataSource:
{
transport:
{
read:
{
url: AppPath + '/DashB/GetWorkProducts'
, contentType: 'application/json; charset=utf-8'
, type: 'GET'
, dataType: 'json'
}
}
, schema: {
model: {
id: "ID"
, fields: {
"ID": { type: "number" }
, "Number": { type: "string" }
, "Name": { type: "string" }
, "Status": { type: "string" }
}
}
}
}
, dataBound: function onDataBound(e) {
//alert('Data bound fired');
}
, change: function onCaseGridChange(arg) {
if (DEBUG)
debugger;
var cells = this.select();
var name = null;
if (cells.length > 0)
name = this.dataItem(cells[0]);
if (name.ID != null) {
// store the currently selected work product
_selectedWorkProduct = name.ID;
// refresh the party dial gauge
_dashViewUI.refreshDialGauge(PARTY_GAUGE, AppPath + '/DashB/GetCaseChildrenCount');
// reload the tasks for the selected work product
$(TASKS).data().kendoGrid.dataSource.read({ workProductID: _selectedWorkProduct });
}
}
});
};
The selected grid row will not be retained if you reload the grid. You have to store it before hand.
var selectedDataItem = grid.dataSource.getByUid(grid.select().data("uid"));
grid.dataSource.read();
if (selectedDataItem) {
var uid = grid.dataSource.get(selectedDataItem.id).uid;
grid.select('tr[data-uid="' + uid + '"]');
}
Here is a live demo: http://jsbin.com/USahiPor/1/edit

DOJO onclick on a pie chart slice for drill down

I tried to find several places how this work but could not.
The requirement is to drill down by clicking on the slice of the pie to next level. I can get the onclick even but not sure how to get the value from the chart. Everywhere it is pointing to http://www.sitepen.com/blog/2008/05/27/dojo-charting-event-support-has-landed/ but nowhere any live demo is given. Till now i have managed to get the onclick.
chart.addSeries("Monthly Sales - 2010", chartData);
var h = chart.connectToPlot("default", function(o){
if(o.type == "onclick"){
alert("clicked!");
}
});
var store = new dojo.store.Memory({data: [
{ id: '2', value: 10, usedForDrillDown:'x' },
{ id: '3', value: 5, usedForDrillDown: 'y' },
{ id: '4', value: 8, usedForDrillDown:'z' }
]});
// adapter needed, because the chart uses the dojo.data API
var storeAdapter = new dojo.data.ObjectStore({
objectStore: store
});
var ds = new dojox.charting.DataSeries(
storeAdapter/*, { query: { needed if the store contains more than data points } }*/);
var chart = new dojox.charting.Chart("chart");
chart.addPlot("default", { type: "Pie" });
chart.addSeries("default", ds);
chart.connectToPlot("default", function(evt) {
if(evt.type == "onclick"){
var itm = evt.run.source.items[evt.index];
console.dir(itm);
}
});
chart.render();

Resources