I have a tableadapter implementation in my application extended from TableModelAdapter and for some reason I want to make tablemodel empty (delete all data inside model) and refill it with new values
is it posible
Update your underlying data as needed and then call TableModel.modelReset() to notify the TableView that a big change has occured.
Related
A Vaadin grid shows data which is constantly updated by a background process. A user might select one or more rows to carry out various functions. The user might refresh the data from the backend (which updates rows shown in the grid).
The application needs to restore the selected items after a grid refresh.
grid.getSelectedItems() has to return the current instance of the selected items.
Refresh is implemented as follows:
void refresh() {
final var beanSet = grid.getSelectedItems();
dataProvider.refreshAll(); // refresh from backend
grid.asMultiSelect().select(beanSet); // restore previously selected items
}
Updating the grid works fine, but the selection is only partly restored: the "selected" checkbox is checked for the items in beanSet but querying grid.getSelectedItems() still returns the old instances.
Reproducer: https://github.com/skiedrowski/vaadin-grid-restore-selection, package com.example.application.views.idstyle -> check the notification after clicking "Update selected".
What is the correct way to update the selected items?
Context:
Vaadin Flow 23, Grid Pro in multiselect mode
grid items implement equals and hashCode based on an immutable id
grid data provider is a ConfigurableFilterDataProvider fetching paged data from backend
I believe the problem in your sample project is that you're always recycling a set of selected objects which contain the "old" data. You read out a reference to the old items in var beanSet = grid.getSelectedItems(); and store them back into the selection with grid.asMultiSelect().select(beanSet);
A lazy-loading Grid can't know if the programmatically set selection is a collection of objects that are available in the backend - it would need to fetch the entire backing dataset to do that. So when the selection is updated from the server, it could be any objects of the correct type, whether they actually exist in the data set or not.
What could do yourself is pass the selection set to the backend, update the items and then pass them back to the Grid's selection.
An open question that remains is whether Grid should update the selection when a fetch returns items that are equal to items in the selection. I can't immediately tell if that is
a) possible, or
b) a sensible thing to do
This is how we solve this in our application:
A]
fresh items are retrieved lazily
the only time when refreshed selection is needed is when we want to operate with the selected items (such as edit or another action, otherwise obsolete selected items don't matter)
the backend is able to return fresh item by ID
there is no need to update the selection on fetch() (which could introduce inconsistencies if a part of the selection is already updated but the rest haven't been fetched yet)
B]
we have some data providers which just hold wrappers for actual items
so any interaction with the items fetches fresh data under the hood
for the record, this was not done to solve this problem but mitigates it as a sideeffect
I'm attempting to have my individual UITableViewCells: I'd love to have the initial values of the model brought over to their UI representation as well as after the user makes a change have the new UI value brought back to the model. Let's just focus on the latter first: UI changes propagating to the model.
For a little more background understanding, I'm running into an issue when adding a new item. This table is driven by an NSFetchedResultsController which sends one didChangeObject with a ChangeInsert and a second didChangeObject for ChangeUpdate. The ChangeInsert triggers an insertRowsAtIndexPaths on the table and the ChangeUpdate does a reloadRowsAtIndexPath.
Because of these two responses my table view asks for cellForRowAtIndexPath twice. This shouldn't be a problem if the same cell is disposed of properly between requests but it doesn't appear to be: I receive an assert that the property in the model is already bound to a RACSignal! I've tried any number of ways to be more explicit such as:
RAC(self.model,value) = [ [RACSignal merge:#[self.valueField.rac_textSignal] ] takeUntil:self.rac_prepareForReuseSignal]
however the reuse signal does not fire in time as it still asserts (aside, is there a recommended way to directly debug a signal like this firing?)
I've tried adding an additional takeUntil:[RACObserve(self, model) to dispose of the signal as soon as the reused cell's model is overwritten (and have it bind to the new model) and understandably this seems to result in the first value disposing. However adding skip:1 to the observe puts me right back where I am.
Please let me know if there is anywhere else I can add clarity or if you have another way to lay these things out. I'm very new to Reactive Cocoa and still learning best practices :)
Thanks!
I have a tableView, and I am adding rows to it from different sources. Using the original widget library I was able to attach data to the insertRow method, but since upgrading to 2.0 that now seems impossible.
How I think I should be able to attach data:
list:insertRow{
rowHeight=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor,
data=data[i]
}
data should then be accessible inside the touch event:
local function onRowTouch( event )
print( event.target.data )
end
Since widget2.0 this is not the case. My question is this: how can I access that data?
NB: In other parts of the app I have been able to reference the original data table by using the row index as the table key, eg: print( data[event.row.index] ), but I cannot do this on a table with multiple data sources.
I have found an undocumented way of passing data to the table row. I'm placing it here in case anyone finds this thread who is having the same issue. As it is undocumented it may be liable to change at any point.
You can attach data using the following:
list._view._rows[#list._view._rows].data = data
data can be anything, and this works in the same way as adding it into the insertRow method.
To access this data in the touch method it would simply be: event.target.data
The way you do this is to use the index value on the row and inside the onRowRender function you reference your data table:
local function onRowRender(event)
id = event.index
print(data[id])
end
list:insertRow{
rowHeight=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor,
}
With the index value you can fetch whatever you need from your data.
I want to delete items and refresh it. I have been trying for 2 days, no luck.
listField.delete(index) doesn't work.
If you can provide me appropriate solution, I will give you all of my reputation.
You'll probably have to override it to remove the item from your data backing the list, and then call listField.setSize(newSize). Since it doesn't know what sort of data structure you are using to push elements into it, it can't be sure how to remove them.
For example, if you have a Vector that stores your data, override delete() to remove the element, and then call setSize(vector.size()). If your ListFieldCallback is stored somewhere else, just make a wrapper call to a similar delete() method in your callback.
how can i automatically update my entity objects changed values and save them to db.
I hava an Action like that
public ActionResult Update()
{
User userToUpdate = new User();
TryUpdateModel<User>(userToUpdate,ValueProvider);
BaseRepository.Context.AttachTo("User",userToUpdate);
BaseRepository.Context.SaveChanges();
return Json("");
}
ValuProvider : has the items that come
from the client as post data.
The problem on this code is the code update all the values but i want to update only the changed values.
How can i find the changed values on my entity object.
You should check out the ObjectContext.ApplyPropertyChanges Method
it is suppose to do what your asking for...
msdn
Two options:
On the View you could know the values that were changed by using Javascript and then you could pass that information to your controller.
You could simply compare the previous values (which you already have since you populated a view) and check each value before updating the DB.
I prefer last option, since at this point you could also check for data validation.
This is really a problem for your data access code, not anything to do with your controller. Pick an ORM that handles this for you and forget about the problem.