SlickGrid javascript get current row data - javascript

I would like to remove a row when I press the Delete key. But I can't get any data from the source below:
var selectedrows = grid.getSelectedRows();
grid.onKeyDown.subscribe(function(event) {
var item = data[selectedrows.cell];
if (event.keyCode == 46) {
alert(item.hostname);
}
});

First, the getSelectedRows() function returns an Array of the selected column numbers. The way you are trying will return undefined, since that Array doesn't contain any property called cells.
Open this official SlickGrid example demo and try the following:
Select the first row in grid.
Try issuing the following command in your JS debugger console:
grid.getSelectedRows()
Will return you an Array with the selected row number as:
Array [ 0 ]
The returned Array'sfirst element is the row number that you have just selected.
Now that we know the selected row number issue this:
data[grid.getSelectedRows()[0]]
Will return you the selected Object as:
Object { name: "Make a list", complete: true }
If you want to reach a property of the returned Object you could do it as:
var selectedRow = data[grid.getSelectedRows()[0]];
console.log(selectedRow.name);
Will return the property name's value as:
Make a list
Hope this clears up your confusion.

Related

Cypress - Working with div tables - Validating text on each row

I want to check if the first column of each row's text starts with "AA", "BB" or "CC". But I couldn't manage it on div table. I can only select and check the first row (code below). But I also tried with selecting the whole column and tried with using cy.each & cy.wrap and got errors too.
How can I check the first column for each row's text? (Table has 40-45 rows.)
The table looks like this:
Right now I can only check the first row with the code below. How can I check all the rows like this? Is the code below clear to you by the way?
cy.get('div[row-index="0"]')
.eq(1)
.invoke('text')
.then(text => {
const productID = text.trim();
let correctProductIDPrefix = false;
['AA', 'BB', 'CC'].forEach(possibleProductIDPrefix => {
if (!correctProductIDPrefix) {
correctProductIDPrefix = productID.startsWith(possibleProductIDPrefix);
}
});
expect(correctProductIDPrefix).to.be.true;
});
Thanks in advance!
To perform the same test on all rows
select all the rows (change [row-index="0"] to [row-index])
use .each() to run test on all rows
sub-select just the column you want, in case some other column also has the prefix and gives you a false-positive result
use Array.some() method to check at least one prefix matches
const possibleProductPrefixes = ['AA', 'BB', 'CC'] // define once outside test
cy.get('div[row-index]') // selects every row
.each($row => {
const $col = $row.find('[col-id="orderNumber"]') // pick out the column
const productId = $col.text().trim()
const correctProductIDPrefix = possibleProductPrefixes.some(prefix => {
return productId.startsWith(prefix)
})
expect(correctProductIDPrefix).to.be.true;
});
Ref Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
You can do something like this:
let prefix = ['AA', 'BB', 'CC']
cy.get('.ag-cell-value').each(($ele, index) => {
expect($ele.text().trim().startsWith(prefix[index])).to.be.true
})

Angular 2 Filter array and append data

Quick one, I've 2 arrays/ objects. One contains all items the other contains selected ID's from the first array.
My question is, what is the best way to loop through both arrays find selected items from the second array and if they are true append data to first array. What I'm trying to do is append true to the first array if the ID's match.
For example something like this:
this.categories.filter(
category => {
this.user.category_ids.filter(
selected => {
if(selected == category._id) {
var data = {'selected': true};
category.push(data);
}
}
);
console.log(category);
}
);
At the moment I'm looping through categories object then through user.category_ids and if the ID's match I want to append selected: true to first array object, if this makes sense. I get error:
core.es5.js:1084 ERROR TypeError: category.push is not a function
Which I don't understand why. I've also tried splice.
Also to me this doesn't seem like best approach, because I've 12 items in first array. And if all 12 are selected, second array will have 12 items. So looping through 12 * 12 to me is little expensive, memory wise.
You can try something like this:
this.categories.map(category => {
category.selected = this.user.category_ids.indexOf(category._id) !== -1;
return category;
});
if (selected == category._id) {
category['selected'] = true;
/* you can build a interface for category
* or declare category as any
* then you can write it as the below
*/
// category.selected = true;
}
push is to add a new item to an array.
Kindly clarify if categories is an array of objects? If yes then you cant use push to add a new object since each element in the categories is an object and object don't have push method. Add new property to object instead using
category.selected=true or
category['selected']=true;
Assumptions:
this.user.category_ids is a 'array of objects' as you are using 'category._id'.
if ids match you want to add a key 'selected' whose value is true , to that object whose id is matched .
Solution:
- You are getting this error category.push is not a function because category is an object not an array ,push only works with array.
if(selected == category._id) {
category['selected']=true;
}

Custom filter on 'ng-repeat' does overwrite the scope

My aim is to replace the teacher-id(f_teacher) of one outputted array with the teacher name of another array. I wrote a custom filter, that should do the job:
angular.module('core')
.filter('replaceId', function () { //filter, which replaces Id's of one array, with corresponding content of another array
return function (t_D, s_D, t_prop, s_prop) { //data of target, data of source, target property, source property
var replacment = {};
var output = [];
angular.forEach(s_D, function (item) {
replacment[item.id] = item[s_prop]; //replacment - object is filled with 'id' as key and corresponding value
});
angular.forEach(t_D, function (item) {
item[t_prop] = replacment[item[t_prop]]; //ids of target data are replaced with matching value
output.push(item);
});
return output;
}
});
I use a 'ng-repeat' like this:
<tr ng-repeat="class in $ctrl.classes | filter:$ctrl.search | replaceId:$ctrl.teachers:'f_teacher':'prename' | orderBy:sortType:sortReverse">
<td>{{class.level}}</td>
<td>{{class.classNR}}</td>
<td>{{class.f_teacher}}</td>
</tr>
But it only outputs an empty column. Now the strange thing: If I follow the steps with the debugger, it works for the first time the filter is performed. But when it is performed a second time it outputs an empty column.
I noticed that the returned object of the filter overwrites the $ctrl.classes - array, but normally this shouldn't be the case?
Here is a plnkr:
https://plnkr.co/edit/EiW59gbcLI5XmHCS6dIs?p=preview
Why is this happening?
Thank you for your time :)
The first time through your filter the code takes the f_teacher id and replaces it with the teacher name. The second time through it tries to do the same thing except now instead of getting a teachers ID in f_teacher it finds the teacher's name so it doesn't work. You could fix it by making a copy of the classes instead of modifying them directly. e.g.
angular.forEach(t_D, function (item) {
var itemCopy = angular.copy(item);
itemCopy[t_prop] = replacment[itemCopy[t_prop]];
output.push(itemCopy);
});
https://plnkr.co/edit/RDvBGITSAis3da6sWnyi?p=preview
EDIT
Original solution will trigger an infinite digest because the filter returns new instances of objects every time it runs which will cause angular to think something has changed and retrigger a digest. Could you just have a getter function that gets a teachers name instead of using a filter?
$scope.getTeacherName = function(id) {
var matchingTeachers = $scope.teachers.filter(function(teacher) {
return teacher.id == id;
})
//Should always be exactly 1 match.
return matchingTeachers[0].prename;
};
And then in the HTML you could use it like
<tr ng-repeat="class in classes">
<td>{{class.level}}</td>
<td>{{class.classNR}}</td>
<td>{{getTeacherName(class.f_teacher)}}</td>
</tr>
https://plnkr.co/edit/gtu03gQHlRIMsh9vxr1c?p=preview

AngularJS forEach set object properties in ng-repeat found set

I have an ng-repeat displaying items from json, based on what the user enters into a field it can be filtered.
<tr ng-repeat="i in filteredItems = (iso3166 | filter: {alpha_2: isoQuery})">
this all works as expected.
Each item in the group ("iso3166") has 3 boolean values, "restricted", "unrestricted", and "unclassified", for each of the columns "license", "prohibited", and "size".
The user can set one of these values in each column in each row to true or false:
This works fine.
What I need to add is an "ALL" row at the top that will set every item in the filtered set to whichever button was clicked in each column.
In other words, if the user clicks the ALL rows "restricted" button in the "license" column, every row's "license" "restricted" value should be toggled to true or false. I'm not sure of the syntax to set the value.
Now I have the ng-click as
ng-click="setAll('col1','licensed')"
and the function as
$scope.setAll = function (column, value) {
angular.forEach($scope.filteredItems, function (value, key) {
??
});
};
How do I assign the correct value to each row in the loop?
At the moment your inner function shadows the value variable. Rename the local variable to something else in order to change it.
$scope.setAll = function (column, value) {
angular.forEach($scope.filteredItems, function (item, key) {
item[column] = value;
});
};

Getting a row from a data attribute in datatables.js

I am struggling trying to find the right method to do this. Basically, I have an array of id values that correspond to which rows have been selected in my table. To construct this list, I use the following code. this.options.ajaxId is the key that accesses my Id value in the data object passed to the table.
this.getRowData(target)[this.options.ajaxId]
where my getRowData function is:
getRowData: function (HTMLrow) {
return this.dataTable.row(HTMLrow).data();
},
This works great, but then I am stumped on my next step which is re-selecting the correct rows when the table is re-drawn via paging, sorting, or searching. My plan was to cycle through the ID's and find which table row corresponded to that ID value, but I cannot find a function to input a key value search pair and return the html row. Something like the following is what I was thinking,
this.dataTable.findRow( key, value );
// then my usage would be the following:
var that = this;
_.each(this.selectedList, function (id) {
var row = that.dataTable.findRow( that.options.ajaxId, id );
// code to select the row
});
I haven't written it yet, but I know I can cycle through each of the rows, get the data for that row, and check it against what I am looking for, but in cases where the user is viewing 100 rows and has only one selection I would like to avoid that.
Any insight?
Thanks
SOLUTION #1
You can use the following code to locate and highlight rows based on row IDs if row ID is stored in one of the fields.
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
// Find indexes of rows which have IDs in the desired column
var rowIndexes = table.rows().eq(0).filter( function (rowIdx) {
return ($.inArray(table.cell( rowIdx, colIdIndex ).data(), rowIds) !== -1)
? true
: false;
});
// Select rows based on array of found row indexes
table.rows(rowIndexes)
.nodes()
.to$()
.addClass('selected');
See filter() API method for more details.
Please note that this method will work for client-side processing mode only.
DEMO
See this jsFiddle for code and demonstration.
SOLUTION #2
Alternative approach that would work both in client-side and server-side processing modes would be to use createdRow callback.
For example:
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
var table = $('#example').DataTable({
createdRow: function( row, data, dataIndex ) {
if ( $.inArray(data[colIdIndex], rowIds) !== -1) {
$(row).addClass('selected');
}
}
});
DEMO
See this jsFiddle for code and demonstration.

Categories