reload table in WatchKit - watchkit

We have a hierarchical watch app.
The root controller is a table of menu items. That list of items is controlled by a server. The data is retrieved and stored in core data. The menu is populated the first time going into the app.
But I want this table to stay current. My thought was to add code to willActivate to check if there was changes, and reload the table. In my reload logic I call the same function I called the first time, which sets the menuTable.setNumberOfRows and creates each row. Looking at what I'm putting in the logs, it is going through this logic with a different count of rows and new labels. But the app on the watch shows the table with the old data.
How can I get this table to reload with the new information?

I've had this problem too and as rmp says, it still seems to be a bug in watchOS 1.0.1. The problem appears when you try to reload your tableView after run willActivate() and nothing will happen.
In my case, I reload the tableView after receive a reply from a delegate and then I reload all the content just if it's necessary. To achieve this, I remove all rows from a NSIndexSet and load again.
if isNecessary {
self.table.removeRowsAtIndexes(NSIndexSet(indexesInRange: NSMakeRange(0, maxItems)))
isNecessary = false
}
I've tried a lot of tricks but none has worked for me:
Force to reload rows by table.setNumberOfRows(0, withRowType: "data")
Setting parameters to empty text before assign new values
One thing you could do is to hide tableView before removing rows, and avoid the remove animation.

It is a bug in WatchKit. Seems like Apple doesn't handle the repetitive interface object correctly.
The general principle here is: Only insert or remove necessary rows after a table is created. Do not reload the whole table like what we usually do in iOS. It just doesn't work (or trigger the bug).
So specifically, you have to:
Do this in willActivated method. This is correct.
If this is the first load, before the table is even created, do what you are now doing – load all table rows.
For all following times, don't reload the table, fetch the new data and check the desired number of rows.
Compare with the current number of rows in the table, insert to or remove from the bottom of the existing table.
Now simply re-assign the new data to all existing rows. Again, do not reload.
It should work if you follow the above steps.

I have found what works best given the current state of watchkit is to remove all rows then re-populate the table.
Try something like this:
- (void)loadTableData{
//clear the table
[mainTableView setNumberOfRows:0 withRowType:#"myTableRow"];
//set the row count again
[mainTableView setNumberOfRows:numberOfRows withRowType:#"myTableRow"];
//populate table
}

Its pretty simple. As Apple hasn't provided any method to reload the data.
You can still achieve that by simply populating the rows for the tableview.
Below is the sample code:
for index in 0..<tracksTableView.numberOfRows {
if let controller = tracksTableView.rowController(at: index) as? EditPlaylistRowController {
controller.playingTrackId = self.playingTrackID
controller.sharedTrack = trackItems[index]
}
}
Use it whenever you want to refresh the data.
NOTE:
You can still make some conditional statements inside the row controller class.
Happy to help :)

Related

Powerapps - get stuck with UpdateContext

I am trying to build a PowerApp to log setup times of our machines by our fitters.
This is what my app looks like:
There are buttons named "Uhrzeit". Pressing these will write the current date and time into the Date/Time fields. I am using the following code:
UpdateContext({Total8:(Text( Now(); "[$-de-DE]dd/mm/yyyy hh:mm:ss" ))})
The Date/Time field is named Total8.
The code is working well but after saving the form and opening a new record the old data is still available in the fields. By clicking on the button "Zeiten zurücksetzen" I can "delete" the old data.
UpdateContext({Total8:""})
Problem: When I open one of the older records the old data is not available in the form. There is only the value of the last record. In the Common Data Service where my records are saved the values are correct.
As an example, I am saving this record:
When I open a new record, the values of the record 1 are still available. This should not be the case if my app worked properly.
For your Information:
If I enter the date/time without tapping the button, saving the record and opening a new record I don't have the problem. I think the "UpdateContext" code is not the code I should use here.
Can anyone help me solve the problem?
I don't think there's a problem with using the contexts in this way -- but remember that a context is just a variable. It isn't automatically linked to a datasource in any special way - so if you set it equal to Now(), it's going to keep that value until you do something different.
When you view an old record, you need to get the data from CDS and update your contexts to match the CDS data. Does this make sense?
Yeah thats my problem.
I want the variable to be linked to a datasource. Or is it possible to write the date/time into the fields without using a context variable?

Count of the icon tab filter

I would really like to understand how to use the "count" property of the IconTabFilter for SAPUI5 to dynamically show the count of the result set of a table.
I have the following code -
<IconTabFilter
count="{DataSet/$count}">
<Table items="{DataSet}">
But the count is not filled automatically.
I am using an oData model that is bound on the view level. I do not want to make another backend request just for the counts. What am I doing wrong here? Is there a different mechanism that can be used?
I also tried using the updateFinished event on the table to then get the count and set it via JS but the event is triggered only on DOM placement of the table. In my case the table is hidden behind the IconTab and is not placed into the DOM till the first time the user clicks the tab so its useless.
Really would appreciate some insight into how to use this!
Thanks!
Okay, so what I did was I bound my information to a local model and did an oData $expand query to fetch the entire pages information in one call.
This worked out for me because I had several sets of data to be fetched. Before they were bound individually to tables, now they are all in one query.
In the .done() method of the call I just used the setCount method of the IconTabFilter to set the count as per the return data set.

Qt: QSqlTableModel + QTableView sync with PostgreSQL

I'm writing a database access app for storing some data and want to ask a few questions about the model/view architecture.
(Using: Qt 4.7.4, own build; PostgreSQL 9.0; Targets: WinXP, Win7 (32/64 bit))
Let me first explain what I am trying to achieve and where I am currently.
I have two pages (subclassed QWidgets inserted in a QStackedWidget) with a QTableView bound to a model. Each view is bound to a table in the PostgreSQL server. You can add/edit/delete/sort/filter items.
Each page can be seen by only one type of users, lets call the roles Role1 and Role2.
The submit strategies of everything connected to the model are OnManualSubmit.
(Transaction isolation level = Serializable.) When two users want to edit(for example) the same row, I want to do a "SELECT ... FOR UPDATE" query - to make sure that when someone edits something, he will merge his changes with newer ones (if any, just like in SVN for example). But I see only a submitAll() method the QSqlTableModel.
Maybe catching the signals beforeUpdate(), beforeDelete(), beforeInsert() and performing manually "SELECT ... FOR UPDATE" is one option.
The other way I think is to subclass QSqlTableModel. What is the clean and nice way to achieve this?
I want to periodically update the QSqlTableView for each of the pages (one page is seen at most, Role1 users have access only to Page1 and the same for Role2 => Page2).
The first thing that came to my mind is to use a QTimer and manually call select() of the QSqlTableModel, but... not sure if this is the cool way.
I also want to periodically check if the connection to the database is ok, but I think that a QTimer + QSqlDatabase::isOpen () will do.
Now, the 2 tables have the same primary keys and some columns are the same. I want when a user with Role1 changes a row in Table1 to automatically change corresponding columns of Table2 and vice versa. Should I create a trigger in Postgres?
BTW, the database is small - each of the two tables is around 3-4000 rows with ~10 columns (varchars mostly, 1 text and 2 date colunms).
Thanks for reading and Happy New Year! :)
I think you should consider doing something of the following:
Instead of using QSqlTableModel as a model I'd implement my own model as a subclass of QAbstractTableModel. This will allow you a lot of control over what you can do in terms of data manipulation.
One thing that this will require is for certain fields in the table you would need to implement subclass of QAbstractItemDelegate that will allow for modification of data in the table as I am fairly sure you don't want to allow users updating any field in the table as for example primary key is likely have to be left alone.
For question 2 I would suggest implementing a field called transaction_counter for every row so you don't have to select every row in the table just the updated ones the transaction_counter will be updated on every row update and the new one will be inserted on the new row insert. One thing that will be required is that the counter is unique across the table. For example if initial state of the table is: row1 has counter = 0 and row2 has counter = 0. If row1 is updated counter set to 1. When row1 is then updated again counter on it is set to 2. When row2 is now updated counter on it is set to 3, etc. You can certainly do the data refreshes now using QTimer and this will be much more advantageous to for example checking the data as one user may be updating the same table as another user with the same Role.
For Question 3. I don't see any reason why not custom models and especially if you decide to separate data from the model you can manipulate data separately from it's display. Sort of Data->Model->View->Controller implementation. Each one can be maintained separately as long as you have a feedback mechanism for your delegates.
For Question 4. The answer is sure or you can implement the trigger in your application.
Hope this helps. Have a great New Year!

Keep selection when refreshing datagrid in ActionScript

I'm working on my first ever AIR application with flashbuilder - just so you know.
I've bound a mx:DataGrid component to a DataProvider which is a mx:HTTPService fetching an xml file with items. To keep the data up to data I'm polling the webservice on a given interval.
My problem is that I loose the currently selected item in my DataGrid when the data is updated. I've tried to save the DataGrid.selectedIndex and set when the data is updated, but I'm not sure when to do it?! The closest I've come is to restore the index when the updateComplete event of DataGrid is fired. This works, but the selection first fades away and then fades in - not updated soon enough.
So what is the best way to keep the selection? (only one selected item at a time)
And as a side question: is there a convenient way to only update the data when it has actually changed?
Thankful for any suggestions!
I'll start from the bottom, the only way to only update the data when it has changed is to pass a check on the data on the server side to see if data has changed and make that a call before the actual update. So in short, you make two calls, one to see if the data has changed, which is a server side query, and the next only if that returns true, which updates the data.
Alternatively, you can also get the update, and compare it to your current data, and only update the UI if that data is different, but I have a feeling you mean the former answer of only doing the update CALL at all, if the data has changed.
As for the other solution, after you've saved the selectedIndex, do this inside your updateComplete:
private function yourDataGridUpdateComplete(event:FlexEvent):void{
yourDataGrid.selectedIndex = yourIndex;
yourDataGrid.validateNow();
yourDataGrid.scrollToIndex(yourIndex);
}
The DG uses the UUID of the data items to determine whether the item should be still selected after a refresh. If the data items don't implement IUID they basically get random values created each time they are added to the DG.
If your data items implement the IUID and you use a consistent value (DB sequence number for example) the DG will "know" that after a refresh, the data item is the same one as before.

Two tables on one page Asp.Net

My project is in Asp.Net Webforms using C#.
On one of my web pages, I want to have two tables. One is going to be a summary table and the other a more detailed breakdown of the summary. When the user clicks on one of the rows of the summary table, I want the corresponding breakdown rows to appear in the breakdown table.
These tables can have anything between 60 and about 500 rows.
I have thought of two possible ways of doing this and I'm not sure which is best, or if there is another, better way of implementing this:
1) When a user clicks on one of the rows in the first table, a postback event happens, and the data for the second table is loaded from the code behind.
2) When the webpage is loaded for the first time, both tables are filled with all of the possible data, but all of the rows in the second table have the "display: none;" CSS attribute. When a user clicks on a summary row, the CSS of the corresponding breakdown rows is changed using JavaScript.
I'd go with your first thought and perhaps either
load the data for the second table through an AJAX request returning only row data in JSON (or maybe even the HTML for the table)
use an UpdatePanel
if the user only needs to view the data, I would go for the former, but if they need to edit the data in some way, I would probably choose the latter (even though I'm aware that UpdatePanels are effectively a full postback in async clothing, I feel their use can make the UI more fluid).
You could also make an AJAX call when the user clicks on a row in the summary table to return the data for the 2nd table.
second way no way, loading all of data and then hiding showing is not a good idea, it will be slow and if you add more functionality it will only get in your way...
I recommend this two approaches:
1)first table with pagination
click on row triggers ajax call to page method
page method return second table
here, you can see how to that:
http://encosia.com/2008/02/05/boost-aspnet-performance-with-deferred-content-loading/
2)using of uframe
http://labs.omaralzabir.com/UFrame2005/
cheers

Resources