I have this simple fiddle:
http://jsfiddle.net/anilca/kbfssbd4/
var dataArr = [
{ DayNum: 0, Day: "Sunday", Group: "A" },
{ DayNum: 1, Day: "Sunday", Group: "B" },
{ DayNum: 2, Day: "Sunday", Group: "C" },
{ DayNum: 3, Day: "Monday", Group: "B" },
{ DayNum: 4, Day: "Monday", Group: "A" },
{ DayNum: 5, Day: "Tuesday", Group: "C" },
{ DayNum: 6, Day: "Tuesday", Group: "B" }
];
var grid = $("#grid").kendoGrid({
dataSource: {
data: dataArr,
sort: [
{ field: "DayNum", dir: "asc" },
{ field: "Group", dir: "asc" }
],
schema: {
model: {
fields: {
DayNum: { type: "number" },
Day: { type: "string" },
Group: { type: "string" }
}
}
}
},
selectable: true,
columns: [
{
field: "Day",
title: "Day"
},
{
field: "Group",
title: "Group"
}
]
}).data("kendoGrid");
I want to show empty cells for Day column for the row after the first appearance of the appropriate day. I mean my aim is to have the following screenshot without manipulating the data:
I thinks it's possible to do that using jquery after building the kendo grid. But I couldn't find out how to do it.
Thanks in advance,
I would do it using schema.parse method. This method manipulates the data but doesn't changes it, which is good. And no jQuery needed:
parse: function(data) {
var lastDay = "";
for (var i = 0; i < data.length; i++) {
if (lastDay == "" || data[i].Day != lastDay) {
lastDay = data[i].Day;
}
else {
data[i].Day = "";
}
}
return data;
}
Updated Fiddle.
UPDATE:
Yeah, I was wrong when I said that the parse doesn't changes the data. IN fact it changes. What you can do is to create dummy property and manipulate it:
parse: function(data) {
var lastDay = "";
for (var i = 0; i < data.length; i++) {
if (lastDay == "" || data[i].Day != lastDay) {
lastDay = data[i].Day;
data[i].DayText = data[i].Day;
}
else {
data[i].DayText = "";
}
}
return data;
}
See that I'm using(and creating) DayText this time. Your first column definition changes to:
{
field: "DayText",
title: "Day"
}
So it keeo the Day property as is. Fiddle.
I threw a jQuery-each function at the end that seems to do the trick, try adding it to the bottom of your javascript:
var day = ""; // holds latest day value
// for each row...
$('tr').each(function(){
var thisDay = $(this).find('td:first').html(); // grab the text from the first column
if (thisDay == day) // if its the same as last time
{
$(this).find('td:first').html(''); // hide it
}
day = thisDay; // hold onto this day
});
Related
I've got a deeply nested array that looks like this:
const elements = [
{
type: "section",
id: "basic-section",
title: "Basic information",
children: [
{
type: "select",
label: "Entity type",
id: "entity-type",
options: [
{ value: "person", label: "Person" },
{ value: "company", label: "Company" },
{ value: "organisation", label: "Organisation" },
],
},
{
type: "group",
conditions: [
{ type: "isEqual", variable: "entity-type", value: ["person"] },
],
children: [
{ type: "text", label: "First name", id: "entity.firstName" },
{ type: "text", label: "Last name", id: "entity.lastName" },
{ type: "number", label: "Age", id: "entity.age" },
{
type: "select",
label: "Gender",
id: "entity.gender",
defaultValue: "female",
options: [
{ value: "male", label: "Male" },
{ value: "female", label: "Female" },
],
},
],
},
{
type: "group",
conditions: [
{
type: "isEqual",
variable: "entity-type",
value: ["company", "organisation"],
},
],
children: [
{ type: "text", label: "Name", id: "entity.name" },
{ type: "text", label: "Address", id: "entity.address" },
],
},
],
},
];
I'm trying to add and update a property based on a given key and value.
Example 1: Add an option to the options list of entity-type
Example 2: Update the defaultValue of entity.gender to male
My current steps to accomplish this actions are:
1) Find the element based on the id key and id value
const element = findObject(elements, 'id', 'entity-type');
function findObject(object, key, value) {
if(object.hasOwnProperty(key) && object[key] === value) {
return object;
}
for(let i = 0; i < Object.keys(object).length; i++){
if(typeof object[Object.keys(object)[i]] == "object") {
const o = findObject(object[Object.keys(object)[i]], key, value);
if(o !== null) return o;
}
}
return null;
}
2) Create new option
const newOption = { value: 'government', label: 'Government' };
3) Add the new option to the found element
const updatedElement = Object.assign({}, element, { options: [...element.options, newOption] });
4) Replace the old element with the updatedElement
const newElementsList = // Stuck
5) Update the state with the updatedElementsList
setElementsList(newElementsList);
I don't see how I can replace the original element with the updated one based on the key and value.
Can someone help me out?
This is not recommended, but you can keep track of parent. Once you find the element, update the parent data with update value. But you loose immutability.
A better approach would be found and update the same time.
const elements = [{"type":"section","id":"basic-section","title":"Basic information","children":[{"type":"select","label":"Entity type","id":"entity-type","options":[{"value":"person","label":"Person"},{"value":"company","label":"Company"},{"value":"organisation","label":"Organisation"}]},{"type":"group","conditions":[{"type":"isEqual","variable":"entity-type","value":["person"]}],"children":[{"type":"text","label":"First name","id":"entity.firstName"},{"type":"text","label":"Last name","id":"entity.lastName"},{"type":"number","label":"Age","id":"entity.age"},{"type":"select","label":"Gender","id":"entity.gender","defaultValue":"female","options":[{"value":"male","label":"Male"},{"value":"female","label":"Female"}]}]},{"type":"group","conditions":[{"type":"isEqual","variable":"entity-type","value":["company","organisation"]}],"children":[{"type":"text","label":"Name","id":"entity.name"},{"type":"text","label":"Address","id":"entity.address"}]}]}];
// console.log("%j", elements);
function findObject(element, key, value, { parent = null, index = -1 }) {
if (element.hasOwnProperty(key) && element[key] === value) {
return { element: element, parent, index };
}
let keys = Object.keys(element);
for (let i = 0; i < keys.length; i++) {
if (typeof element[keys[i]] == "object") {
const o = findObject(element[Object.keys(element)[i]], key, value, {
parent: element,
index: i,
});
if (o !== null) return o;
}
}
return { element: null };
}
const { element, parent, index } = findObject(
elements,
"id",
"entity-type",
{}
);
const newOption = { value: "government", label: "Government" };
const updatedElement = Object.assign({}, element, {
options: [...element.options, newOption],
});
if (parent && index !== -1) parent[index] = updatedElement;
console.log(JSON.stringify(elements, null, 4));
I am making my own filter system for filtering data, and I'm building the basic functionality now, such as adding and removing filters.
Adding filters works fine, but when I play around with adding and removing, sometimes splice removes more than one filter. Why is it doing that? here is my code:
var active_filters = [];
var available_filters = [
'first_name', 'last_name', 'city'
];
var filters = {
first_name: {
title: 'First Name',
is_active: false,
types: [
{
input: 'text'
},
{
input: 'select',
options: [
'asc', 'desc'
],
values: [
'Ascending', 'Descending'
]
}
],
},
last_name: {
title: 'Last Name',
is_active: false,
types: [
{
input: 'text'
},
{
input: 'select',
options: [
'asc', 'desc'
],
values: [
'Ascending', 'Descending'
]
}
],
},
city: {
title: 'City',
is_active: false,
types: [
{
input: 'text'
},
],
},
};
var id_filters = $("#filters");
$(document).ready(function () {
id_filters.html(template_filters(filters));
});
function template_filters(filters) {
var html = '<select class="select_filters" id="select_filters" onchange="add_filter();">';
html += '<option value="0">Select Filter</option>';
for (var property in filters)
{
if (filters.hasOwnProperty(property))
{
var title = filters[property].title;
var is_active = filters[property].is_active;
var types = filters[property].types;
html += '<option value="'+property+'">'+title+'</option>';
}
}
html += '</select>';
return html;
}
function template_show_filter(filter, filter_name)
{
var html = '<div id="filter-'+filter_name+'" class="div_filter">';
html += '<span>'+filter.title+' X</span>';
html += '</div>';
return html;
}
function add_filter()
{
var select_filters = $("#select_filters");
var selected_filter = select_filters.val();
if (selected_filter != 0)
{
if (active_filters.length == 0)
{
active_filters.push(selected_filter);
id_filters.append(template_show_filter(filters[selected_filter], selected_filter));
}
else
{
if (active_filters.indexOf(selected_filter) === -1)
{
active_filters.push(selected_filter);
id_filters.append(template_show_filter(filters[selected_filter], selected_filter));
}
}
}
}
function remove_filter(filter_name)
{
var index = active_filters.indexOf(filter_name);
if (index >= 0)
{
var id = $("#filter-"+filter_name);
id.remove();
active_filters.splice(index); // here, it removes more than one
}
}
Please have a look at MDN web docs – Array.prototype.splice().
If you want to remove only one item, you should call .splice(index, 1).
If you don’t specify the second argument, “then all of the elements beginning with start index on through the end of the array will be deleted.”
This is because you are splicing at index.
active_filters.splice(index);
This will remove all elements after the index value.
My array is like this
$scope.ebObjArr = [{key: 'val', monthsArray: [{myDate:'',}]},{myDate:'',}]
monthArray is used for filling the sub-grid. I can't figure out how to set data for the sub-grid.
I tried this:
for (let i = 0; i < $scope.ebObjArr.length; i++) {
$scope.ebObjArr.monthsArray[i].subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, {name:"Units consumed", field : "unitsConsumed"}],
data: $scope.ebObjArr[i].monthsArray
}
}
I tried this too :
for (let i = 0; i < $scope.ebObjArr.length; i++) {
for (let j = 0; j < $scope.ebObjArr[i].monthsArray[j].length; j++) {
$scope.ebObjArr[i].monthsArray[j].subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, { name: "Units consumed", field: "unitsConsumed" }],
data: $scope.ebObjArr[i].monthsArray[j]
}
}
}
I'm using only the MainCtrl in this example: http://ui-grid.info/docs/#/tutorial/216_expandable_grid.
I'm sure there's a better way to do this but since no one answered I did this and it worked.
onRegisterApi: function (gridApi) {
$scope.grid1Api = gridApi;
$scope.grid1Api.expandable.on.rowExpandedStateChanged($scope, function (row) {
if (row.isExpanded) {
console.log(row.entity);
row.entity.subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, { name: "Units consumed", field: "unitsConsumed" }],
}
row.entity.subGridOptions.data = (function () {
var a;
a = $scope.ebObjArr.filter(function (val) {
if (val.ebName === row.entity.ebName && val.ebAddress === row.entity.ebAddress) {
// console.log(val.monthsArray);
return val.monthsArray
}
return false;
});
console.log(a);
console.log(a[0].monthsArray);
return a[0].monthsArray;
})();
console.log(row.entity.subGridOptions.data);
}
});
}
I am having jqgrid this way,
<div id="dialogLoading" style="position:absolute;z-index:1005">
<img src="http://blog.teamtreehouse.com/wp-content/uploads/2015/05/InternetSlowdown_Day.gif" />
</div>
<table id="list"></table>
$(function () {
var blueArray = [];
for (var i=1;i<=4000;i++) {
blueArray.push(i);
}
var greenArray = [];
for (var i=4000;i<=6000;i++) {
greenArray.push(i);
}
var redArray = [];
for (var i=6000;i<=8000;i++) {
redArray.push(i);
}
var yellowArray = [];
for (var i=8000;i<=10000;i++) {
yellowArray.push(i);
}
"use strict";
var getGridData = function(n) {
var data = [], i;
for (i = 0; i < n; i++) {
data.push({
id: (i + 1)*10,
aa: "aa" + i, // colunn 1
bb: "bb" + (i%3), // colunn 2
cc: "cc" + (i%5), // colunn 3
dd: "dd" + (i%7), // colunn 4
ee: "ee" + (i%11), // colunn 5
ff: "ff" + (i%13), // colunn 6
gg: "gg" + (i%17), // colunn 7
hh: "hh" + (i%19), // colunn 8
ii: "ii" + (i%23), // colunn 9
jj: "jj" + (i%29), // colunn 10
kk: "kk" + (i%31), // colunn 11
ll: "ll" + (i%37), // colunn 12
mm: "mm" + (i%41) // colunn 13
});
}
return data;
},
$grid = $("#list"),
gridData,
startTime,
measureTime = false,
timeInterval;
gridData = getGridData(10000);
startTime = new Date();
$grid.jqGrid({
data: gridData,
colModel: [
{ name: "aa", label: "c01" },
{ name: "bb", label: "c02" },
{ name: "cc", label: "c03" },
{ name: "dd", label: "c04" },
{ name: "ee", label: "c05" },
{ name: "ff", label: "c06" },
{ name: "gg", label: "c07" },
{ name: "hh", label: "c08" },
{ name: "ii", label: "c09" },
{ name: "jj", label: "c10" },
{ name: "kk", label: "c11" },
{ name: "ll", label: "c12" },
{ name: "mm", label: "c13" }
],
cmTemplate: { width: 100, autoResizable: true },
iconSet: "fontAwesome",
rowNum: 10000,
rownumWidth: 40,
//rowList: [20, 100, 1000, 10000, "100000:All"],
viewrecords: true,
rownumbers: true,
//toppager: true,
//pager: true,
shrinkToFit: false,
rowattr: function (rd) {
var rowIds = $("#list").jqGrid('getDataIDs');
console.log(rowIds);
if(blueArray.indexOf(rowIds) > -1)
return {"class": "blue"}
else if(greenArray.indexOf(rowIds) > -1)
return {"class": "green"}
else if(redArray.indexOf(rowIds) > -1)
return {"class": "yellow"}
else
return {"class": "one"}
},
loadComplete: function () {
closeDialogLoading();
if (measureTime) {
setTimeout(function () {
alert("Total loading time: " + timeInterval + "ms");
}, 50);
measureTime = false;
}
},
autoencode: true,
caption: "Shows the performance of resizing. Make double-click on the column resizer"
}).jqGrid("gridResize");
timeInterval = new Date() - startTime;
setTimeout(function () {
alert("Total time: " + timeInterval + "ms");
}, 50);
function openDialogLoading(){
$("#dialogLoading").css("display", "");
}
function closeDialogLoading(){
$("#dialogLoading").hide();
}
});
css:
.one { background:red; }
.blue { background:blue; }
.green { background:green; }
.yellow { background:yellow; }
I am trying to chaNge the row color of the jqgrid comparing each rowid with an array of values.
Here is the logic for that,
rowattr: function (rd) {
var rowIds = $("#list").jqGrid('getDataIDs');
console.log(rowIds);
if(blueArray.indexOf(rowIds) > -1)
return {"class": "blue"}
else if(greenArray.indexOf(rowIds) > -1)
return {"class": "green"}
else if(redArray.indexOf(rowIds) > -1)
return {"class": "yellow"}
else
return {"class": "one"}
the problem here is, rowIds are getting as empty []. so always my condition i going to else and red color is shown on each row's.
I need to check if rowid is exists in blueArray,greenArray e.t.c if its is true paint that row with the corresponding color.
In my example my bluearray has values from 1 to 4000. So all these records from 1 to 4000 have to be painted in blue.
My logic inside rowattr: block is not working as i am getting rowid as empty[].
How to get rowid inside rowattr: function (rd) {} block of jqrid?
The above logic working is fine in loadcomplete and gridcomplete events but it is blocking entire ui and taking hell lot of time to load grid.
Can anyone help me in this issue?
Thanks
You need just use rd.id inside of rowattr:
rowattr: function (rd) {
if (blueArray.indexOf(rd.id) > -1) {
return {"class": "blue"};
} else if (greenArray.indexOf(rd.id) > -1) {
return {"class": "green"};
} else if (redArray.indexOf(rd.id) > -1) {
return {"class": "red"};
} else {
return {"class": "one"};
}
}
the demo uses the code, but it's really slowly because you create 13x10000 cells in the grid. I recommend to open the demo only in Chrome where it takes still about 15 sec.
I strictly recommend to use local paging. Look at almost the same demo where the page size is 25 instead of absolute unneeded 10000. It works really quickly. One can jump on the page 200 or 300 to see another colors.
I have a Object to dynamically fill my DropDown list.
var myOptions = [
{ name: Projekte[1][1], value: "val1" },
{ name: Projekte[2][1], value: "val2" },
{ name: Projekte[3][1], value: "val3" },
{ name: Projekte[4][1], value: "val4" },
{ name: Projekte[5][1], value: "val5" },
{ name: Projekte[6][1], value: "val6" },
{ name: Projekte[7][1], value: "val7" },
{ name: Projekte[8][1], value: "val8" },
{ name: Projekte[9][1], value: "val9" },
{ name: Projekte[10][1], value: "val10" }
];
it looks like ther will be up to 100 Projects when the code is in charge, so how can I set name and value of this Object to the right length?
what i tried before was this:
var anzahlproj =100; //how many project i get
var myOptions = [
{ name: Projekte[1][1], value: "val1" }
];
for(var i=2;i<anzahlproj + 1; i++){
myOptions[name] +="Projekte["+i+"][1]",
myOptions[value] += "val"+i;
}
add something to a normal Object is no problem, but how can I add something with multiple elements?
I use: JQuery 1.11.1, JQuery Mobile 1.4.3
var myOptions = [], i;
for (i = 1; i <= 100; i++) {
myOptions.push({name: Projekte[i][1], value: "val" + i});
}
Try this code
var anzahlproj = 100; //how many project i get
for (var i = 2; i < anzahlproj + 1; i++) {
var myOption = new Option(Projekte[i][1], "val" + i.toString());
myOptions.append($(myOption));
}