How to update the columnDef of an angular ui-grid column dynamically - javascript

So the issue I'm facing is I would like to update the field property of a columnDef definition to show a different value based on some configuration that's being passed into the directive. I have a dumbed down version in this plunk:
http://plnkr.co/edit/gmjUcQsnIOpqWwkoYiI8?p=preview
Clicking the button in that plunk should switch the emails from actual to pretend. It's looping over the columnDefs on scope and then altering the field to be email.pretend from email.actual. Do I need some kind of "refresh" function after changing the columnDefs? I tried gridApi.core.refresh() but that did not do anything. Thanks for any input!

http://plnkr.co/edit/ujIpJFFGRAwNUKiy0Bnm?p=preview
$scope.otherColumn = {displayName: 'Pretend', field: 'email.pretend'};
//change the field - is this possible???
$scope.changeField = function changeField() {
$scope.otherColumn = $scope.columnDefs.splice(1, 1, $scope.otherColumn)[0];
}
You just add / remove the item from the columnDefs array and it will do it.

So I thought I could update my grid similar to this but by reassigning an array to the columnsDef like this
var a = true;
//change the field - is this possible???
$scope.changeField = function changeField() {
if (a) {
$scope.columnDefs = [{ field: 'name' }, {
displayName: 'Pretend',
field: 'email.pretend'
}];
} else {
$scope.columnDefs = [{ field: 'name' }, {
displayName: 'Email',
field: 'email.actual'
}];
}
a = !a;
};
If you put that in the plnkr you'll see it doesn't have any effect.
That's because the assignment doesn't change the $scope.gridApi.
As #dave's answer suggests you need to modify the original columnsDef object from the initialization or the columns under the api won't be affected. I'm glad the code doesn't clone the object for the api or I'd have to dig into the api to make this change.

Related

jquery kendo grid filter property is undefined

I have a jquery function that should filter the datasource based on the Service Type value of the button that was clicked.
I used this post on telerik to get my guidance:
Adding filters to Grid's source
From that, I created this buttonFilter() function:
function buttonFilter() {
var buttonText = 'All';
var button = $('#ReadTypeBtnGroup > button.btn.btn-default.active');
if (button != null) {
buttonText = button.val();
}
console.log('buttonFilter:: buttonText: ' + buttonText);
var dataSource = $('#grid').data('kendoGrid').dataSource;
if (dataSource.filter() != undefined) {
dataSource.filter().length = 0; // remove any existing filters
}
if (buttonText != 'All') {
dataSource.filter().push({ field: "serviceType", operator: 'eq', value: buttonText });
}
return buttonText;
}
The error I am getting is:
Uncaught TypeError: Cannot read property 'push' of undefined
The filter() property is supposed to be an array, but I am not great when it comes to javascript or jquery.
What am I doing wrong?
You got it wrong. You can't change filter properties changing the result of filter() method. Instead, you have to use it passing parameters. That method only returns readonly values.
Example:
var filters = dataSource.filter(); // Getting current filters
dataSource.filter(null); // Clearing filters
dataSource.filter({ field: "abc", value: "1" }); // Setting new filters
Always check the docs
#Dontvotemedown is largely correct, and that answer will work well for what you specifically want to do (i.e. clear filters completely and apply your own). However, if you want to manually add a filter to existing filters, your original path was close to correct. I found this answer in my original search, then this when I couldn't add to an undefined filter. My full solution for adding a filter, either to an undefined filter set, or along with an existing one:
var grid = $("#ActivityGrid").data("kendoGrid");
var dataSource = grid.dataSource;
var gridFilter = dataSource.filter();
var upcomingFilter = {
field: "ActivityDate",
operator: "gte",
value: new Date(),
FilterName: "UpcomingOnly"
};
if ($("#UpcomingOnlyCheckbox")[0].checked) {
if (gridFilter == undefined) {
dataSource.filter(upcomingFilter);
}
else {
gridFilter.filters.push(upcomingFilter);
dataSource.filter(gridFilter);
}
}
I had the same problem. If no filters exist, dataSource.filter() returns undefined which is a problem if you want to add filters. But using something like
dataSource.filter({ field: "abc", value: "1" });
results in a datasource read operation which was undesired in my case. Therefore I manipulated the datasource properties.
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
var filterConfig = dataSource.filter();
if (typeof filterConfig == 'undefined') { //no filters exist
filterConfig = { filters: [], logic: "and" };
grid.dataSource._filter = filterConfig;
}

Deleting a row using api.updateRowData(transaction) has no effect on data source

I have a custom cell renderer to delete given entity.
function ActionButtonsCellRenderer() {}
ActionButtonsCellRenderer.prototype.init = function(cellRenderParams) {
var tempDiv = document.createElement('div');
var deleteButton = document.createElement("a");
deleteButton.href = "javascript:void(0)";
deleteButton.innerHTML = "<i class='fa fa-trash'></i>";
tempDiv.appendChild(deleteButton);
deleteButton.addEventListener("click",function(){
cellRenderParams.api.updateRowData({remove: [cellRenderParams.data]})
});
this.eGui = tempDiv.firstChild;
};
ActionButtonsCellRenderer.prototype.getGui = function() {
return this.eGui;
};
It actually deletes the row from GUI. No problem there.
But when user adds another row using below logic;
function addRow() {
var row = {t1 : "test"}
dataSource[dataSource.length] = row;
agGridOptions.api.setRowData(dataSource);
}
Deleted row also became visible again in the grid. Which means that the dataSource object is not updated.
What am I doing wrong here ? The dataSource must be updated in my scenario.
Isn't there a two-way binding which I can use ?
For deleting the selected rows use this code,
this.selectedNodes = this.GridOptions.api.getSelectedNodes();
this.GridOptions.api.removeItems(this.selectedNodes);
this.GridOptions.api.refreshView();
Now selected Row will be deleted.
Ag-grid makes a copy of the data that you provide to it. So when you are using updateRowData, ag-grid will update the data that it has, not your original data array. This is good design to avoid unexpected results and loss of original data.
There are two possible solutions to your issue:
mutate your original data anytime you need to update the data - this will likely get really messy really fast
--- OR ---
use the ag-grid's built in functionality of allowing it to update row data, then when you need to do something with the dataSource (such as downloading in an excel or sending to some other function) use the getModel() function to get the data that ag-grid is aware of.
For anyone that come across this post i know its a long time ago but.
I had to add and remove a row from one table to another without UI selection
Lets say we have a grid with common columnDefs e.g. headersName, fields ( its important to have fields) and etc.
We gonna have 2 columns:
{
headerName: 'Name',
field: 'name',
cellRenderer: params => params.data.name,
....
},
{
headerName: 'Age',
field: 'age',
cellRenderer: params => params.data.age,
....
},
What i did was:
const item = {
'name': 'New name',
'age': 25,
}
* Remove a row - if the grid already have this item
this.gridApi.updateRowData({ remove: [item] });
* Add row - if the grid doesn't have it
gridApi2 is your seconds grid table api
this.gridApi2.updateRowData({ add: [item] });
add/remove: [item] - it has to be array
if you need to refresh for some reasons (sometime change detector does't update ) there is 2 AgGrid refresh options: Refresh Cells and Redraw Rows..for this case i will use refreshCells()
this.gridApi.refreshCells({ force: true });
this.gridApi2.refreshCells({ force: true });
used materials: https://www.ag-grid.com/javascript-grid-data-update/
section: Full CRUD & Bulk Updating
method: Method 2 - Transaction
This works for me. Of course here we are assuming that we have a grid working e.g. (gridReady)="onGridReady($event)"

Dojo OnDemandGrid won't display data

I'm using arcgis javascript api 3.19 which includes dojo. I'm trying to display some data in a grid and edit it. Right now, the data won't display in the grid.
I'm using the tutorial to learn how to use this grid, [http://dgrid.io/js/dgrid/demos/laboratory/][http://dgrid.io/js/dgrid/demos/laboratory/]
I've embedded their sample code in my widget and it doesn't work.
(Rather than include my whole widget, I'll just show the sample code.)
It doesn't find the dgrid/Editor, but it can find dgrid/editor.
The grid header and an empty box for the data shows up, but no data.
require([
'dojo/_base/declare',
'dstore/Memory',
'dstore/Trackable',
'dgrid/OnDemandGrid',
'dgrid/Keyboard',
'dgrid/CellSelection',
'dgrid/Editor' // I have to use dgrid/editor for this to be found
], function (declare, Memory, Trackable, OnDemandGrid, Keyboard, CellSelection, Editor) {
var store = new (declare([Memory, Trackable]))({
data: createData()
});
// Instantiate grid
var grid = new (declare([OnDemandGrid, Keyboard, CellSelection, Editor]))({
collection: store,
columns: {
First_Name: {
label: 'First Name',
editor: 'text'
},
Last_Name: {
label: 'Last Name'
}
}
}, 'grid');
grid.startup();
function createData() {
var data = [];
var column;
var i;
var item;
for (i = 0; i < 50; i++) {
item = {};
for (column in { First_Name: 1, Last_Name: 1 }) {
item.id = i;
item[column] = column + '_' + (i + 1);
}
data.push(item);
}
return data;
}
});
Ok, I found the answer.
Esri has two directories in their javascript api, dgrid and dgrid1.
And the files in them are largely the same (by filename at least)
Apparently the "correct" classes are in dgrid1, not dgrid.
I suppose there might be a good reason for putting the code in a differently named directory than the documentation, but from where I'm sitting, not knowing that reason, I can only say "Thanks for letting me beat my head against a wall for two days on this. Thanks so very much."

Jquery: Autocomplete with label

I am trying to learn website development.
While learning autocomplete feature of jquery, I tried to put in the labels.
function autocomplete (data) {
var data = data.toString();
var availableTags = data.split(',');
var autocompleteData = [];
for (var i = 0; i < availableTags.length; i++){
autocompleteData[i] = {};
autocompleteData[i].label = i.toString();
autocompleteData[i].value = availableTags[i];
}
$("#tags").autocomplete({
source: autocompleteData,
select: function (event, ui) {
printautocomplete(event, ui)
}
});
};
The autocomplete[i].value is a valid string.
autocompleteData[0]
Object {label: 0, value: "Peter"}
However, I do not see any suggestions.
What is wrong with the way I am using the API?
The API says:
"Array: An array can be used for local data. There are two supported formats:
An array of strings: [ "Choice1", "Choice2" ]
OR An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will be inserted into the input element when a user selects an item. If just one property is specified, it will be used for both, e.g., if you provide only value properties, the value will also be used as the label. "
Thank you.
$('#sidebarSearch').autocomplete(
{
source: function(query, result)
{
var query = $('#sidebarSearch').val ();
$.ajax(
{
url:"sidebarSearchFetch.php",
method:"POST",
data:{query:query},
dataType:"json",
success:function(data)
{
result($.map(data, function(item)
{
return {
label: item.name,
value: item.usrId
};
}));
}
})
},
appendTo: "#sidebar-form"
});
I am skeptical of line 2 in your code (var data = String()data;) I would use: var data = data.toString();
But if you are sure that the autocompleteData elements do indeed have valid strings, then my best guess would be that perhaps you forgot to give the '#tags' id to your html entry field element.
Finally, if this is not it, to troubleshoot, I would try removing the select: option from the object you are passing to autocomplete() in the line that begins: $("#tags").autocomplete(... so that only the source options is passed.
Another thing to check out is when the code is being run. It is possible that a document.ready() function is needed to ensure that that when the autocomplete feature is added to the DOM element with the id '#tags', that the element has already been created.
The autocomplete works fine. Instead of completing "value", it completes "label".
So when I type in "1", it suggests "1", "10", "11", etc.
Autocomplete applying value not label to textbox answers how to change to to by-value.

Computed values in knockout koGrid

I need to use a grid in which one column has a computed value based on values from other columns in the grid ...
As a sample requirement I have one column which shows the age this is a editable column ... if the age is changed the next column should compute the value of 100 - the updated age ...
I have created a jsfiddle to demo my requirement here JSFiddle
{field: 'computedAge', displayName: '100 -Age',cellTemplate:self.calculatedCellTemplate}
is the computed column that i wish to populate when the age column is updated
Can anyone suggest how i could achieve this ?
You can achieve this by only two steps:
(1) Create instantiation function for every item in your datalist with computedAge computed property within it.
function Item(data) {
this.name = ko.observable(data.name);
this.age = ko.observable(data.age);
this.computedAge = ko.computed(function(){
return 100 - this.age();
}, this);
}
(2) Map source array to create instances instead of simple observableArray creation.
self.browsers = ko.observableArray(
ko.utils.arrayMap(
datastore.initialData,
function(data){ return new Item(data); }
)
);
Working example: http://jsfiddle.net/xp6xa/
Update:
To get self-updating cell do not forget to define your self.calculatedCellTemplate like this:
self.calculatedCellTemplate = '<span data-bind="text: $parent.entity.computedAge"></span>';
http://jsfiddle.net/xp6xa/3/

Categories

Resources