Reputation: 6294
I am using the ag-grid for angular1, (and loving it), and I want my users to be able to reorgenize columns, change sortings, and everything, and that it will stay after a refresh. It should not be very hard, except that the columns are circular (contains pointers to themselves), and thus I cannot parse them.
Code:
var columnDefsKey = "columnDefs["+$rootScope.page+"]";
var savedColumns = localStorage.getItem(columnDefsKey);
function saveColumnsState() {
var currentCol = vm.gridOptions.columnApi.getAllColumns();
if (!angular.equals(currentCol, savedColumns))
try {
localStorage.setItem(columnDefsKey, JSON.stringify(currentCol));
} catch (ex) {
log(ex);
log(currentCol);
}
}
And:
onColumnEverythingChanged: saveColumnsState,
onColumnVisible: saveColumnsState,
onColumnPinned: saveColumnsState,
onColumnResized: saveColumnsState,
onColumnRowGroupChanged: saveColumnsState,
onColumnValueChanged: saveColumnsState,
onColumnMoved: saveColumnsState,
onColumnGroupOpened: saveColumnsState,
It fails on the "try" every time: TypeError: Converting circular structure to JSON(…) [Column, Column, Column, Column, Column, Column, Column, Column, Column, Column]
How can I do that? (save columns for later use)
If I manage to do that, I will be able to create several views without coding.
Upvotes: 1
Views: 1786
Reputation: 6294
The way to achieve this was to build my own column model, that I can save and parse again, and in which to save only necessary properties.
This method is XSS vulnerable, as I am evaluating functions, but it is a working solution.
columnsApi: {
key: null,
grid: null,
newColumnModel: {
headerName: "",
width: 200,
valueGetter: "",
filter: 'text',
aggFunc: 'none',
filterParams: {apply: true}
},
setKey: function (key) {
this.key = key;
},
setGrid: function (grid) {
this.grid = grid;
},
format: function (columns) {
var format = [];
angular.forEach(columns, function (col) {
var colDef = {
width: col.actualWidth,
pinned: col.pinned,
hide: !col.visible
};
format.push(angular.extend(col.colDef, colDef));
});
return format;
},
getIDs: function (columns) {
var ids = [];
angular.forEach(columns, function (col) {
ids.push(col.colId);
});
return ids;
},
stringify: function (columns) {
return JSON.stringify(columns, function (key, value) {
if (typeof value === "function")
return "/Function(" + value.toString() + ")/";
return value;
});
},
parse: function (string) {
return JSON.parse(string, function (key, value) {
if (typeof value === "string" &&
value.startsWith("/Function(") &&
value.endsWith(")/")) {
value = value.substring(10, value.length - 2);
return eval("(" + value + ")");
}
return value;
});
},
add: function (column) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
if(column.aggFunc == 'none')
column.aggFunc = undefined;
var groups = this.get().groups;
var newColumns = this.format(getGridColumns(this.grid));
newColumns.push(column);
this.grid.api.setColumnDefs(newColumns);
this.setGroups(groups);
},
save: function () {
var self = this;
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var savedOptions = {
columns: self.format(getGridColumns(self.grid)),
groups: self.getIDs(self.grid.columnApi.getRowGroupColumns()),
sorting: self.grid.api.getSortModel(),
filter: self.grid.api.getFilterModel()
};
localStorage.setItem(this.key, this.stringify(savedOptions));
},
// Get function uses "eval" - XSS vulnerable.
get: function () {
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
var options = localStorage.getItem(this.key);
if (options)
options = this.parse(options);
return options;
},
remove: function (field) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var newColumns = this.format(getGridColumns(this.grid));
angular.forEach(newColumns, function (col, key) {
if (col.field == field)
newColumns.splice(key, 1);
});
this.grid.api.setColumnDefs(newColumns);
},
setGroups: function (groups) {
var self = this;
angular.forEach(groups, function (id) {
angular.forEach(getGridColumns(self.grid), function (col) {
if (col.colId == id)
self.grid.columnApi.addRowGroupColumn(col);
});
});
}
}
This solution was written for Ag-Grid 5 I believe, and thus I am not sure if it still holds.
Upvotes: 0
Reputation: 388
you can get the better understanding of the issue from below link
Chrome sendrequest error: TypeError: Converting circular structure to JSON
Also check below reference
https://github.com/isaacs/json-stringify-safe
Upvotes: 2