2 Arrays are addItems and testSelectAll, Whenever I push to addItems I also want to update testSelectAll.
addItems has individual checkbox state from the following grid while testSelectAll has per column (header) checkbox state. So in the following case, testSelectAll will have 2 items while addItems will have 6.
My useEffect is as follows:
useEffect(() => {
var check = areAllSamplesSelectedForTest(data.TestId);
if(check)
{
console.log(testSelectAll.length)
//updateSelectAll(data.TestId, true)
}
}, [addItems]);
As soon as I uncomment updateSelectAll (it updates testSelectAll), my header checkbox starts behaving abnormally
PS: I have two useEffects in my component, one is to load data one-time to table with empty array as dependencies.
Related
We've just moved over from bootstrap to Vuetify, but i'm struggling with something.
We have some updates sent (over signalR) that update a list of jobs, i'd like to be able to target a job that has been changed and change the row color for that particular job for a few seconds so the operator can see its changed.
Has anyone any pointers on how we can do this on a Vuetify v-data-table
Thanks
I ran into the same problem. This solution is a bit crude and a bit too late, but may help someone else.
In this example I change the colour of the row permanently until the page reloads. The problem with a temporary highlight is that if the table is sorted there is no way to put the row in the visible part of the table - v-data-table will put it where it belongs in the sort, even if it's out of the view.
Collect the list of IDs on initial load.
Store the list inside data of the component.
Use a dynamic :class attribute to highlight rows if the ID is not in the list (added or edited rows)
Solution in detail
1. Use TR in the items template to add a conditional class.
<template slot="items" slot-scope="props">
<tr :class="newRecordClass(props.item.email, 'success')">
<td class="text-xs-center" >{{ props.item.email }}</td>
:class="newRecordClass(props.item.email, 'success')" will call custom method newRecordClass with the email as an ID of the row.
2. Add an additional array to store IDs in your data to store
data: {
hydrated: false,
originalEmails: [], <--- ID = email in my case
3. Populate the list of IDs on initial data load
update(data) {
data.hydrated = true; // data loaded flag
let dataCombined = Object.assign(this.data, data); // copy response data into the instance
if (dataCombined.originalEmails.length == 0 ) {
// collect all emails on the first load
dataCombined.originalEmails = dataCombined.listDeviceUsers.items.map( item => item.email)
}
return dataCombined;
}
Now the instance data.originalEmails has the list of IDs loaded initially. Any new additions won't be there.
4. Add a method to check if the ID is in the list
newRecordClass(email, cssClass) {
// Returns a class name for rows that were added after the initial load of the table
if (email == "" || this.data.originalEmails.length==0) return "" // initial loading of the table - no data yet
if (this.data.originalEmails.indexOf(email) < 0 ) return cssClass
}
:class="newRecordClass(..." binds class attribute on TR to newRecordClass method and is being called every time the table is updated. A better way of doing the check would be via a computed property (https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties). Vue would only call it when the underlying data changed - a method is called every time regardless.
Removing the highlight
You can modify newRecordClass method to update the list of IDs with new IDs after a delay to change the colour to normal.
#bakersoft - Did you find a solution? I suspect there is an easier way to skin this cat.
grid.dataItem(selectedRow)
this is return the selected row which is a kendo.data.ObservableObject.
this object has all the columns for that grid's selected row. Is there a way to iterate thru all the columns and update.
or do i have to do it like this:
dataitem.set("Id", 1);
dataitem.set("name", Eric);
dataitem.set("age", 12);
As far as I understand what you are trying is to copy one JavaScript object into a Grid item, correct?
Let's assume that you have the new value in val:
var val = {
Id : 1,
name: "Eric",
age: 12
};
And you want to copy it in the selected row.
There are several ways of doing it:
What you just did.
Iterate through the different keys of val and copy the value.
Use jQuery extend.
Option 2.
for (var key in val) {
if (val.hasOwnProperty(key)) {
dataitem.set(key, val[key]);
}
}
Option 3.
$.extend(item, val);
item.set("uid", kendo.guid());
The first instruction performs a deep copy of val into item.
The second instruction makes the item dirty by just changing the UID.
NOTE: You don't need to update every single field using set, is enough changing one and all will get updated.
In my WPF application, I have a Data Grid which populates with a ObservableCollection collection. Suppose I have such 10 student data in the grid. Each student is capable of doing 2 long running works or process and updates the status of the process back to the grid. I want to do those 2 process simultaneously. So I used Task and Parallel.Invoke methods. The work flow is as follows.
I populated the Student data collection in the Grid.
I clicked on a start button.
In the click event of the start button, i did the following code.
foreach (Student stud in StudentLists)
{
stud.Status = "started..";
Task.Factory.StartNew(() => StartProcess(stud));
}
In the StartProcess,
Parallel.Invoke(() =>
{
MarkService ms = new MarkService(stud_data);
Student s = ms.GetMarkProcess(); // This will return the stud_data in the above line
Student studitem = StudentLists.Where(x => x.RollID == s.RollID).FirstOrDefault(); // find the student in the grid
if (studitem != null)
{
studitem.Status = "Mark Got it"; // if find, updating the status
}
},
() =>
{
SentMarks(poll); // this is another method to be executed parallel
}
);
When executing all the 10 students process, each student in the grid became the same data.
Or only 2 or 1 student in the Grid is showing Status "Mark Got it". Other rows show "started.." status only.
Why this is not updating the collection.
I have used INotofyPropertyChanged and raisng the event when property updated.
In the XAML, each binding is used in Two way mode.
There is no error. But the 1 or 2 items in the student collection is updating some times. Sometimes the collection contains the last students data for all the 9 items.
It is not updating the exact student object in the Grid. what is wrong in my code ?
Any help in this case ???
The problem here is that your referencing a UI control from another thread. You should create an in memory data structure that a grid can use as DataSource (anything that implements IEnumerable). I would suggest using the ConcurrentBag data structure for parallelized code (http://msdn.microsoft.com/en-us/library/dd997305.aspx). Once you've updated each of the student records in the ConcurrentBag you set the grid's datasource to that bag.
On my grid, after a user enters text on the bottom row, I am adding another row so they can fill out another row if needed. The grid will grow as needed by the user. This is working fine, however after a page reload and populating from db, the addrowdata() function does not honor existing row ids and creates duplicates, starting from 1 again, e.g. jqg1. It should look at existing row ids and create new unique ids. So if I have 5 rows already, it might start at jqg6. Here is the relevant code inside onCellSelect:
var records = jQuery("#table-1").jqGrid('getGridParam', 'records');
var lastRowId = jQuery("#table-1").jqGrid('getDataIDs')[records - 1];
if (lastRowId == id)
{
jQuery('#table-1').addRowData(undefined, {}, 'last');
}
I have also tried $.jgrid.randId() instead of undefined, same results as expected.
Thanks
Ryan
I think that the error is in the part where you fill grid with the data from the database. The data saved in the database has unique ids. The ids are not in the form jqg1, jqg2, ... So if should be no conflicts. You should just fill the id fields of the JSON with the ids from the database.
One more possibility is that you just specify the rowid parameter (the first parameter) of addRowData yourself. In the case you will have full control on the new ids of the rows added in the grid.
The code of $.jgrid.randId function is very easy. There are $.jgrid.uidPref initialized as 'jqg' and $.jgrid.guid initialized to 1. The $.jgrid.randId function do the following
$.jgrid.randId = function (prefix) {
return (prefix? prefix: $.jgrid.uidPref) + ($.jgrid.guid++);
}
If it is really required you can increase (but not decrease) the $.jgrid.guid value without any negative side effects.
In my Enyo app, I have a VirtualRepeater which produces Controls containing various text displays and an IntegerPicker.
I have two problems with this repeater:
1) If three rows are produced, clicking on the IntegerPicker in rows 1 and 2 brings up the drop-down picker UI over the top of the IntegerPicker in row 0.
2) I initialise each IntegerPicker with a max value using setMax(). However, if three rows are produced, the IntegerPickers in rows 0 and 1 will have the same max value as that in row 2.
It looks as if only one IntegerPicker is being created and is being used on the first row.
I tried replacing my VirtualRepeater with a Repeater, and changed my repeater row creation function to return a new instance of the item containing the IntegerPicker, instead of returning true. However this produces the error:
warning: enyo.Component.addComponent(): Duplicate component name "itemName" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.
It seems that Repeaters need their delegates created inline, which seems quite inelegant.
This code sample illustrates the problem:
enyo.kind({
name:"Test",
kind:enyo.Control,
components: [
{
kind: "VirtualRepeater",
onSetupRow: "setupRow",
components: [{
name: "theIP", kind: "IntegerPicker", min:0
}]
}
],
setupRow: function(inSender, inIndex) {
if (inIndex < 3) {
this.$.theIP.setMax(inIndex);
return true;
}
return false;
}
});
How can I create an arbitrary number of IntegerPickers in my app? Any help appreciated!
What you are doing with theIP in your setupRow function is accessing a specific IntegerPicker itself, which is a child component of the Virtual Repeater. To set the max value of a given IntegerPicker corresponding to the row, give your VirtualRepeater a name attribute, like "PickerList":
kind: "VirtualRepeater",
onSetupRow: "setupRow",
name: "PickerList",
components:[//this should be empty to begin with]
Then you can access each row in the repeater like this:
setupRow: function(inSender, pickerMax) {
var newPicker = new IntegerPicker(pickerMax);
this.$.PickerList.push(newPicker);
To get a specific row in the VirtualRepeater you need to do it like this:
this.$.PickerList[1];
Here is an extended Enyo tutorial which makes use of the VirtualRepeater:
https://developer.palm.com/content/resources/develop/extended_enyo_tutorial.html