JQGrid Dynamic Select Data - select

I have utilised the example code at Example Code at this link
and I have got my grid to show a dynamically constructed select dropdown on add and edit. However when it is just showing the data in the grid it shows the dropdown index instead of its associated data. Is there a way to get the grid to show the data associated with the index instead of the index itself.
e.g. the data on my select could be "0:Hello;1:World"; The drop down on the edit/add window is showing Hello and World and has the correct indexes for them. If the cell has a value of 1 I would expect it to show World in the grid itself but it is showing 1 instead.
Here is the row itself from my grid:
{ name: 'picklist', index: 'picklist', width: 80, sortable: true, editable: true,
edittype: "select", formatter: "select", editrules: { required: true} },
I am filling the dynamic data content in the loadComplete event as follows:
$('#mygrid').setColProp('picklist', { editoptions: { value: picklistdata} });
picklist data is a string of "0:Hello;1:World" type value pairs.
Please can anyone offer any help. I am fairly new to JQGrids so please could you also include examples.

I know you have already solved the problem but I faced the same problem in my project and would like to offer my solution.
First, I declare a custom formatter for my select column (in this case, the 'username' column).
$.extend($.fn.fmatter, {
selectuser: function(cellvalue, options, rowdata) {
var userdata;
$.ajax({
url:'dropdowns/json/user',
async:false,
dataType:'json',
cache:true,
success: function(data) {
userdata = data;
}
});
return typeof cellvalue != 'undefined' ? userdata[cellvalue] : cellvalue ;
}
});
This formatter loads up the mapping of id and user in this case, and returns the username for the particular cellvalue. Then, I set the formatter:'selectuser' option to the column's colModel, and it works.
Of course, this does one json request per row displayed in the grid. I solved this problem by setting 10 seconds of caching to the headers of my json responses, like so:
private function set_caching($seconds_to_cache = 10) {
$ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$seconds_to_cache");
}
I know this solution is not perfect, but it was adequate for my application. Cache hits are served by the browser instantly and the grid flows smoothly. Ultimately, I hope the built-in select formatter will be fixed to work with json data.

If you save in jqGrid ids of the select elements and want to show the corresponding textes then you should use formatter:'select' in the colModel (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:predefined_formatter#formatter_type_select) together with the edittype: "select".
The Usage of stype: 'select' could be also interesting for you if you plan to support data searching.

Related

How to filter an array of object in Mui DataGrid?

I recently changed my tables to Mui-datagrid on Material UI 5, and I have a special use case with an array of objects. I want to enable the phone number filter in this column, but the number is provided as an object list.
phone: [
{ type: "home", number: "795-946-1806" },
{ type: "mobile", number: "850-781-8104" }
]
I was expecting a 'customFilterAndSearch' or an option to customise how to search in this specific field.
customFilterAndSearch: (term, rowData) =>
!!rowData?.suppressedOptions.find(({ description }) =>
description?.toLowerCase().includes(term.toLowerCase())
),
I have made some tries with the filterOperators, but no success yet. I have made a full example here https://codesandbox.io/s/mui-data-grid-vs05fr?file=/demo.js
As far as I can see from the DataGrid documentation I don't see any way to change the filter function for a specific function.
Likely the best workaround for your use case will be converting this to a string be converting the data to a string before you pass it to the datagrid. Though you will lose the styling that you currently do by making the phone type bold.
On second though your best best would probably be to split the phone column into two columns which would probably be the cleanest way of solving your problem
Add helper function.
You could potentially add a helper function to just map all the phone lists to something like mobilePhone or homePhone
const mapPhoneObject = (rows) => {
rows.forEach((row) => {
row.phone.forEach((phone) => {
row[`${phone.type}Phone`] = phone.number;
});
});
return rows
};
I've added a fork of your snippet with my function, it is I think the most viable solution for your problem: https://codesandbox.io/s/mui-data-grid-forked-ppii8y

Ag-Grid Server Side Row Group Key Creator

When using Ag-Grid's server side row model, I am unable to send a custom group key to the server in order to do proper group by queries.
My row data is a simple JSON structure but with one composite object.
row = {
athlete: '',
age: '',
country: {
name: 'Ireland',
code: 'IRE'
},
...
}
I am using the server side row model. To get the grid to display the country name is simple enough as I use the following column definition.
{
headerName: "Country",
colId: "country",
valueGetter: "data.country.name",
enableRowGroup: true
}
However, when I group by the Country column ag-grid sends the groupKey as 'Ireland' from my example above. But I need the group key to be the country code, 'IRE'. I cannot figure out how to generate a groupKey when using the server-side row model.
I have seen the keyCreator method, but this only works for client-side row model. In addition, I have seen the Tree Data Mode which has a callback for getServerSideGroupKey(dataItem) but then callback only gets used when gridOptions.treeData = true and when the treeData option is set to true, a "Group" column is always displayed regardless if a grouping is happening or not. I tested this out by setting isServerSideGroup: function(dataItem) {return false;}
Any help would be appreciated.
I was able to solve this issue by using the dot notation for the column definition's field attribute and a custom cellRenderer.
{
headerName: "Country",
colId: "country",
field: "country.code",
enableRowGroup: true,
cellRenderer: function (params) {
return params.data.country.name;
}
}
This allowed me to display the correct data point from the custom object and when doing server side actions, ag-grid will send the datapoint contained within the field attribute.

Hierarchial JSON model and UI5

I am creating a demo application with JSON data and UI5. The idea (in a nutshell) is provide various information views for a selected item. I am using IconTabBar control. I have created an example scenario so (hopefully) I can explain the problem more clearly.
1.IconTabBar's first tab has list of employees and user can select one by selecting a radio button on the left
2.This takes the user to the next tab that displays say, sales view. The user can click on any tab and move to the respective view.
3.User can modify the information in any view. If the users forgets or ignores to Save the data, the tab color is set to Red.
4.User can Save the data.
5.Some of the views have information in master detail format.
The problem(s) I am facing are:-
1.How to filter the model data based on the item selected in the table?
2.How to update the filtered data and set back to model?
3.I also would like to know whether the data is structured correctly
I am using following code to update the binding path after company is selected. The GREP function is not returning correct values for proposals. It returns ONLY 1 proposal for E001 whereas it should return 2. It doesn't work properly for orders either. I am not sure whether the data is structured correctly.
var oModel_Data = oJSONDataModel.getData();
var oView_Data = oViewDataModel.getData();
var aModelData = oModel_Data[sSelected_Key];
var aViewData = oView_Data[sSelected_Key];
aViewData = jQuery.grep(aModelData, function(data, index) {
return data.id === sSelected_id
})[0];
oView_Data[sSelected_Key]=aViewData;
oViewDataModel.setData(oView_Data);
oViewDataModel.refresh(true);
I am using following code to check whether user has changed data.
var oView_Data = oViewDataModel.getData();
var oModel_Data = oJSONDataModel.getData();
var aViewData = oView_Data[in_sKey];
var aModelData = oModel_Data[in_sKey];
aModelData.forEach(function(item, index, array) {
var valueView = aViewData;
if (item.id === sSelected_id){
//The code here need to consider complex(nested) data types
//Thus it should check type of not only valueView and item
//but also their each and every child elements
/*---------Temporary Solution---------------------*/
var sViewValue = JSON.stringify(valueView);
var sItem = JSON.stringify(item);
var bSameData = sViewValue === sItem;
if (bSameData==true){
flag_data_changed=false;
}else{
return flag_data_changed=true;
}
}
});
My json model is as below.
{
"employees": [
{"id":"E0001" ,
"name":"Alec Stewert"
},
{"id":"E0002" ,
"name":"Debra Manning"
}
],
"sales": [
{"id":"E0001" ,
"sale_q1":"10000",
"sale_q2":"3000",
"sale_q3":"8000",
"sale_q4":"2000"
},
{"id":"E0002" ,
"sale_q1":"8000",
"sale_q2":"3000",
"sale_q3":"7000",
"sale_q4":"5000"
}
],
"proposal":[
{"id":"E0001",
"fi_q":"Q2",
"value":"12000",
"customer":"6000"
},
{ "id":"E0001",
"fi_q":"Q2",
"value":"8000",
"customer":"2300"
}
],
"key_orders": [
{"id":"E0001",
"order_hdr":
[
{"id":"O0001",
"fi_q":"Q1",
"value":"2000",
"customer":"2000"
},
{"id":"O0002",
"fi_q":"Q1",
"value":"2000",
"customer":"2000"
}
],
"order_dtl":[
{
"id":"O0001",
"itm":"Item X",
"Qty":"100",
"rate":"20"
}
]
},
{"id":"E0002",
"order_hdr":
[
{"id":"O0011",
"fi_q":"Q1",
"value":"2000",
"customer":"5000"
},
{"id":"O0012",
"fi_q":"Q1",
"value":"1000",
"customer":"5000"
}
],
"order_dtl":[
{
"id":"O00011",
"itm":"Item Z",
"Qty":"200",
"rate":"10"
}
]
}
]
}
I have investigated online and in SAP Help but failed to understand what needs to be done. Any help is appreciated.
1.How to filter the model data based on the item selected in the table?
If you prepare the JSONModel you can use the Filter
2.How to update the filtered data and set back to model?
If you bind the table to the JSONModel, by default the JSNOModel is 2 way binding so any edited data will be in the JSONModel
3.I also would like to know whether the data is structured correctly
Go through the Example of the Table So you will get an idea of the Model and binding model to the Table

Number of items limited to around 100

I've created the following Input field.
var oCityInput = new Input({ // sap/m/Input
showSuggestion: true,
showTableSuggestionValueHelp: true,
suggestionItems:{
path: "/cities",
template: new ListItem({ // sap/ui/core/ListItem
text: "{cname}",
additionalText: "{provi}"
}),
},
});
The "cities" array contains around 8400 record, but when I type some character the suggestion function it seems that is looking for only in the first 100 items of the array.
I've created an example in jsbin. If you try to looking for the first elements it works... but if you try to type the last city the suggestion will not come out.
In newer versions of SAP UI5 the JSONModel also supports the setSizeLimit() method:
model.setSizeLimit(iNumOfYourJsonEntries);
API description: "Set the maximum number of entries which are used for list bindings."
Be careful because it can lead to performance issues.

KendoUI Autocomplete paging issue

I have a textbox bound to KendoUI autocomplete widget. The JS code looks like this:
var dataSourceImeSearch = {
type: "json",
transport: {
read: {
url: "#Url.Action("ImeSearch")",
contentType: "application/json; charset=utf-8",
type: "POST"
},
parameterMap: function (data, type) {
if (type == "read") {
if (data.filter) {
data = $.extend({ sort: null, filter: data.filter.filters[0] }, data);
} else {
data = $.extend({ sort: null, filter: null }, data);
}
return JSON.stringify(data);
} else {
return JSON.stringify({ model: data });
}
}
},
batch: false,
pageSize: 10,
serverPaging: true,
serverFiltering: true,
serverSorting: true,
schema: {
errors: "Errors",
data: "Data",
total: "TotalRecordCount",
model: myModel
},
error: function (e) {
if (e.errors) {
alert(e.errors);
}
}
};
$("#Ime").kendoAutoComplete({
dataTextField: "PunoIme",
filter: "contains",
minLength: 3,
dataSource: dataSourceImeSearch
});
I am experiencing a weird thing here. Autocomplete is working in terms that when I type the third character it runs to the server and gets JSON data back from there and shows first ten results. The thing is that this textbox is searching large datasets, so for some queries with say 4 characters result set can be more than 1000 items. For some reason the widget is not figuring out that there are more than 10 results and when I scroll down in the autocomplete dropdown which gets shown, it will not fire any search for a second page and so on. You can see that the serverPaging for data source is set to true, but this does not help.
Any help is appreciated. Thank you.
I found out after posting this question that Autocomplete widget does not allow paging by design. This was explained in the KendoUI forums by some Kendo employee as an example of poor UX (if you have autocomplete that needs paging). I would argue that, since in my opinion, the first use case of the autocomplete would be in case of a search of a person, and here I am doing exactly that. The only problem is that if you search by person's second name you can end up with hundreds of results after first 3 or 4 characters and you really need paging for that. If the Kendo people think that this is a case of a bad UX, this should be clearly mentioned in the Autocomplete documentation, and I could really not find any mentioning of it at a single place, and one would think that it might be a good idea to mention something like this to the people so that they don't have to waste all day trying to figure out what went wrong.
In my opinion one of the worst use case examples at all demos at KendoUI web demo pages is the Shared DataSource example, where if you type in 'ch' in the autocomplete textbox in the top, you will end up with 10 results in autocomplete, but 14 in the datagrid bellow. It really strikes me as stupid that nobody in Kendo sees this behavior as odd.
So my answer to my own question would be the following: DO NOT use autocomplete, except in some really really simple use case (I can't really think of a single one that would make sense). I ended up making a whole search form with 5 textboxes and search button in case where I hoped that I was going to be able to use 2 textboxes (one with autocomplete) and a search button.
You have set pageSize:10, which means that only 10 records are returned to the AutoComplete and its dataSource contains only 10 elements, I am afraid that automatic paging is not implemented by default