IgGrid selectRow Issue - javascript

I am trying to implement the "RowSelectors" feature on the iggrid, but it will not change to a the next row.
On further inspection, i have got the selected row method and each row shows the same id. I am returning my data via ajax, if i use static json in a variable and use that as a datasource, it works as expected so not sure what the issue is..
$("#selector").igGrid("selectedRow");
I can only acheive a row change when holding control and clicking..
Object {element: n.fn.init(1), index: 0, id: 3407751001}
then next row is
Object {element: n.fn.init(1), index: 1, id: 3407751001}
Settings..
features: [
{
name: "Sorting",
columnSettings: [
{
columnIndex: 4,
allowSorting: true,
firstSortDirection: "ascending",
currentSortDirection: "descending"
}
]
},
{
name: 'RowSelectors',
enableCheckBoxes: true,
checkBoxStateChanging: function (ui, args) {
return false;
},
multipleSelection: true,
rowSelectorClicked: function (evt, ui) {
// Handle event
},
},
{
name: 'Selection'
}
]

The issue is already resolved, but I'm adding the answer so it doesn't stay unanswered.
The primaryKey column the igGrid uses needs to be a column with unique identifiers for each record.

Related

Document.getElementsByClassName has 0 length but has elements inside

[![Firefox Console][1]][1]In my Vue app I am trying to use mdb-datatable, the table reads data() and sets the rows accordingly. I am setting the row data programmatically after my data is loaded with Ajax. In one column I need to add a button and it needs to call a function. I am trying to add onclick function to all buttons with "status-button" class but something weird happens.
When I print HtmlCollection it has a button inside, which is expected but I can't reach proceedButtons[0], it is undefined. proceedButtons.length also prints 0 length but I see the button in console.
I also tried to add onclick function but probably "this" reference changes and I get errors like "proceedStatus is not a function" it does not see anything from outer scope.
<mdb-datatable
:data="tableData"
:searching="false"
:pagination="false"
:responsive="true"
striped
bordered/>
export default {
name: "Applications",
mixins: [ServicesMixin, CommonsMixin],
components: {
Navbar,
Multiselect,
mdbDatatable
},
data () {
return {
statusFilter: null,
searchedWord: '',
jobRequirements: [],
applications: [],
options: ['Awaiting', 'Under review', 'Interview', 'Job Offer', 'Accepted'],
tableData: {
columns: [
{
label: 'Name',
field: 'name',
sort: 'asc',
},
{
label: 'Date',
field: 'date',
sort: 'asc'
},
{
label: 'Compatibility',
field: 'compatibility',
sort: 'asc'
},
{
label: 'Status',
field: 'status',
sort: 'asc'
},
{
label: 'Proceed Application Status',
field: 'changeStatus',
}
],
rows: []
}
}
}
fillTable(applications) {
let statusButtonId = 0;
applications.forEach(application => {
this.tableData.rows.push({
name: application.candidateLinkedIn.fullName,
date: this.parseDateFromDateObject(application.applicationDate),
compatibility: this.calculateJobCompatibility(application.candidateLinkedIn.linkedInSkillSet),
status: application.applicationStatus,
changeStatus: '<button type="button" class="btn-indigo btn-sm m-0 status-button"' +
' style="margin-left: 1rem">' +
'Proceed Status</button>',
candidateSkillSet: application.candidateLinkedIn.linkedInSkillSet
});
statusButtonId++;
});
},
addEventListenersToButtons() {
let proceedButtons = document.getElementsByClassName("status-button")
console.log(proceedButtons);
console.log(proceedButtons[0])
console.log(proceedButtons.item(0))
/*
proceedButtons.forEach(button => {
button.addEventListener("click",this.proceedStatus);
});
*/
},
[1]: https://i.stack.imgur.com/zUplv.png
From MDN:
Get the first element with a class of 'test', or undefined if there is no matching element:
document.getElementsByClassName('test')[0]
So undefined means no match, even if length is 0...
Since this is not an array, you do not get out-of-bounds exceptions.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
Regarding Arrays
You can't index the list returned from getElementsByClassName.
You can turn it into an array though, and then index it.
ES6
let proceedButtons = document.getElementsByClassName("status-button")
const arr = Array.from(proceedButtons);
console.log(arr[0]);
Old School
const arr = []
Array.prototype.forEach.call(proceedButtons, function(el) {
arr.push(el);
});
console.log(arr[0]);

Interaction with gridData on ui-grid edit events

I am using Angular ui-grid and am pretty new at it. I receive an array of objects to render data for each row. Each object, hence each row , has a field change:false which marks whether any field on that row has been edited or not. I have kept this field visible : false on screen.
However, whenever any change is made to any column of any row, I want to set this field as change:true.
How can this be achieved on the change of a ui-dropdown field or any other field for that matter.
I have this as my changing column:
{ name: "carrier_influence_group", displayName: "Carrier influence group", enableCellEdit: true,
editableCellTemplate: 'ui-grid/dropdownEditor', type:'object', cellFilter: 'cigFilter', editDropdownValueLabel: 'name',
editDropownOptionsArray: [{ id: 10, name: 'Small' }, { id: 11, name: 'Medium' }, { id: 12, name: 'Large' }]
},
I tried looking for any options available. But couldn't find any way in official docs. Kindly suggest a way or some relevant links
You can use the afterCellEdit event for this.
$scope.gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
gridApi.edit.on.afterCellEdit($scope, function (rowEntity, colDef, newValue, oldValue) {
if (newValue !== oldValue) {
rowEntity['change'] = true;
}
});
});

Kendo UI Grid: if I make changes and save them, I can still cancel them afterwards. How to lock them in?

I have a Kendo UI Grid bound to a local data source. If I make some changes and click on "Save changes", and then I click on "Cancel changes", the changes are rolled back. I expected them to be "locked in" because I saved them.
Furthermore, if I make a change, save it, make another change, save again and finally cancel, both changes are rolled back.
See UPDATED fiddle, with problem and solution:
http://jsfiddle.net/q24ennne/7/
My HTML:
<div id="grid"></div>
My JavaScript:
window.gridData = [
{ id: 1, text: "Uno" },
{ id: 2, text: "Dos" },
{ id: 3, text: "Tres" },
{ id: 14, text: "Catorce" },
];
(function() {
$('#grid').kendoGrid({
toolbar: ["save", "cancel"],
editable: true,
saveChanges: function(e) {
gridData = $('#grid').getKendoGrid().dataSource.data();
$('#grid').getKendoGrid().refresh();
console.log("gridData:");
console.log(gridData);
},
columns: [{
field: "text",
title: "No."
}],
dataSource: {
data: gridData,
}
});
})();
Thanks!
You need to include a schema for your datasource that specifies which property is the id of each item. In your case this happens to also be called "id" so add this:
dataSource: {
data: gridData,
schema: {
model: { id: "id" }
}
}
The grid will then correctly track and keep your saved changes.

Backbone update nested attributes

I have a table that displays a collection of models that looks roughly like this:
{
id: 1,
name: "Product",
category: {
id: 1,
name: "CategoryName"
},
{
id: 2,
name: "Another Product",
category: {
id: 1,
name: "CategoryName"
},
etc..
I can select a model from the table and perform an edit on its attributes in a modal. After I finish editing attributes I call save, close the modal and pass an event to refresh my table. In my table view I recieve an event and call fetch with update: true
App.vent.on("refresh:products", function() {
return this.collection.fetch()({
update: true
});
});
However none of the nested attributes, in this case category, get updated without a hard refresh. How I can fix this? Thanks!
try passing reset:true as options to fetch
App.vent.on("refresh:products", function() {
return this.collection.fetch()({
reset: true
});
});
This will stop backbone from merging the data received from the server.

Programmatically Set Constructor Parameters in Javascript

I am trying to interact with a javascript api (bare in mind I have never done this before). An example of what I am attempting to work with is here:
SearchSpring.Catalog.init({
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
});
In the example I want to add a "backgroundFilter" to this with a value:
var cat="MyNewCategory";
cat.value="ANewValue;
How would I add this category and value to the backgroundFilters: listed above?
This is a very common framework initialization pattern when working with frameworks.
Your example code is passing a JavaScript Object {} as a parameter into a function () that is called init.
Taking out all definitions the pattern looks like this:
SomeFramework.frameworkFunction({});
In the above code the {} is an empty object used for initialization. There are two ways that you can work with that object in practice.
Regarding your first code snippet, you can add code into that 'object literal'.
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['My value']
},
Notice the added comma, this is an important tripping point. This may or may not fit your needs, depending on a few factors.
Regarding your second code snippet, you can apply members to JavaScript objects at runtime. What I mean is, your var cat can be added to the anonymous object-literal that is being passed in. Hard to say, but a simple concept. Here is how:
//Say this is initialized in some separate way. //There is a bug here I'll describe later.
var cat="MyNewCategory";
cat.value="ANewValue";
//Extract and name the initialization object. It is verbatim at this point.
var initObject = {
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
};
//Now we can add variables (and functions) dynamically at runtime.
initObject.cat = cat;
//And pass them into the framework initialization in a separated way.
SearchSpring.Catalog.init(initObject);
Now for the bug. I don't know the solution because I do not know what it is intended to do, but I can point out what is potentially incorrect.
var cat="MyNewCategory";
cat.value="ANewValue;
This code is: 1 creating a String Object called cat. 2 changing the value to a new string.
I do not think this is what you really want.
To add a new backgroundFilter, in the separated way above, it would be:
initObject.backgroundFilters.cat = ['A', 'B'];
//Line above would give you this type of definition within the initObject (at runtime):
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['A','B']
},
For this to work it will depend on what the framework is expecting regarding backgroundFilters.
Hope that helps.
All the best!
Nash
I don't quite understand - do you want to have the backgroundFilters categories as structured objects rather than plain strings? If you are in control of the entire API, you can do something like
...
backgroundFilters: {
category: [
new SearchSpring.Catalog.Category("Shirt"),
new SearchSpring.Catalog.Category("Shoes"),
new SearchSpring.Catalog.Category("MyNewCategory", "ANewValue")
],
department: 'Mens'
}
...

Categories