Angular 11 Material DataSource without further Requests to the Server - angular-material

I've been playing around with the example table-schematic for the Material Design [version: 11.0.3] table.
Basically i want to make a request, take the response and display it with the options to sort and limit the displayed items (pagination).
It works fine if I just replace the content of the connect function with "return a mapped Observable of the Response" but then the sorting and pagination obviously don't work anymore (since they are deleted) and i can't figure out how to make them work.
I assume the example pagination and sorting requires the data to be already present when the page loads/initializes (e.g. with a static Array).
Putting the request in the connect() function, saving the objects of the response to a variable and subscribing does work. However the page does not update after filling the initially empty array with data until sorting or pagination settings change. Which would make sense to me.
My question is, how do i get the data in there once and use the same data for pagination and sorting.
Can I even use the schematic in this case or is it misleading?

You can initialize a MatTableDataSource using an array of data, and then it will handle paging, filtering, and sorting locally and not try to fetch any more data.
See this example: https://stackblitz.com/angular/nleleddqmel?file=src%2Fapp%2Ftable-overview-example.ts
This example creates the data array locally, but you would instead use the response from your server request.

Related

Vaadin Grid - Attempted to fetch more items from server than allowed in one go

~1500 data need to be fetched from DB. The code is pretty simple
List<Item> itemList = getItemsFromDB();
Grid<Item> grid = new Grid<>();
grid.addColumn(Item::getID).setHeader("Id").setAutoWidth(true);
grid.addColumn(Item::getName).setHeader("Name").setAutoWidth(true);
grid.setAllRowsVisible(true);
grid.setItems(itemList);
And I got this warning, only the first 1000 data are shown in the grid, the rest are just empty rows.
2022-04-15 15:46:52.475 WARN 19642 --- [nio-8080-exec-6] c.v.flow.data.provider.DataCommunicator : Attempted to fetch more items from server than allowed in one go: number of items requested '1583', maximum items allowed '1000'.
I know I can use lazy loading, but can I do it without it? The size of data will always be around 1500, and I don't actually care that much about how slow it is.
I am using vaadin 14.8.8
The problem comes from setAllRowsVisible and the DoS protection added inside the data provider. It's currently not easily possible to overwrite this without creating your own data provider.
I'm not really sure why you need all the rows visible; this increases the load time for your end user. If your only reason is to have the grid full height, you can just call setHeight on the grid and the let Vaadin handle the callbacks to the server to only fetch the amount of data needed to show on the client.

Filtering Smarttables initial read request

im using a sap Smarttable to display my data from an ABAP Backend server. Additionally im using SmartVariantManagement to apply Variants and make them persistent.
The problem in my Application is the initial Load of the Smarttable. It seems like the table is first loading all the available data without any filters from the inital Variant of my Smartvariantmanagement.
Is there any way to apply the filters of Smartvariantmanagement to the initial Load in the Smarttable?
Or even better: Is it possible to shut down a running odata-read request if i apply a new selection in the smartfilterbar and just run the new one instead?
example 1:
you can avoid the initial request by the smarttable property
enableAutoBinding="false"
you can also set some mandatory fields for filtering, now the user performces an explicit call to the database
example 2:
you can also define a filter in the smarttable function
beforeRebindTable="onBeforeRebindTable"
controller:
onBeforeRebindTable: function (oEvent) {
var oBindingParams = oEvent.getParameter("bindingParams");
oBindingParams.filters.push(new sap.ui.model.Filter("PropertyX", "EQ", "myProperty"));
}
regards

How to fetch all the Todo lists and its corresponding Todos for a project from New Basecamp (bcx) API

REFERRED https://github.com/basecamp/bcx-api/blob/master/sections/todos.md and https://github.com/basecamp/bcx-api/blob/master/sections/todolists.md
TRIED hitting the /todolists.json Basecamp bcx API (since I needed to show the todo lists as header/sections of the tableview displaying Project Todos).
GOT Names of the todo lists, their Descriptions (if any), and their respective URLs (amidst other not-so-useful-to-me info.)
Now, I have already used this URL (above) and hit it to fetch the list of todos (both completed and remaining) for that particular todo-list and got what I intended to; storing and displaying them, dynamically.
However, to me, this approach seems a bit amateurish as I am,a) storing the todo list in a mutable-array..b) hitting the API for each object of this mutable-array (above) and fetching an array of todos for a particular todo-list..c) storing this list (of todos) in a mutable-dictionary - key for which is the name of the todo-list..and finally,d) using this mutable-dictionary in the tableView:heightForRowAtIndexPath: and tableView:cellForRowAtIndexPath: methods for dynamically setting the tableView height and objects, respectively..
INTEND TO Get all the todo lists for a project WITH its corresponding todos as a response of a single Basecamp bcx API, for:
a) Improving the code quality,b) Decreasing the iteration time,c) Preventing headache of a person, if any, who is going to parse my code later in future
This currently isn't possible with the BCX API. If you want to see all of the todos on an individual project's todolists, you'll need to get each todolist separately.
I think this is probably available in the new API update. Kindly check.

RestKit 0.20 and ManagedObjectContexts

I am mapping data using RestKit 0.20 into a Core Data and displaying it in a UITable. I am writing the data, an 'Activity' object, to the mainQueue's ManagedObjectContext and it all works fine. Now I need a second table with Future-Activities and also a third table with Past-Activities. I need a ManagedObjectContext for each table as the sorting is done on the server side. How can I handle this and have persistent data. Is 'newChildManagedObjectContextWithConcurrencyType' what I need to use?
Keep a single store. Use a predicate to filter out the items you want.
If you can download all of the data (and you're happy to do that even though some of it may not be used by the user), and you can tag them for what they are used for then that is an option.
From a RestKit point of view, you can use metadata to tag the items during the mapping process so that you know how they should be used (and then filter on that). This requires that you add a new key to the item - but, if one item could be in all responses this will be problematic because the values would get overwritten.
To use metadata, simply add a new mapping like:
#"#metadata.URL": #"requestURL"
Where #metadata.URL is the URL used to make the request and requestURL is the property on your entity that you can use for filtering. The predicate will check for contains your types ("all_day" "start_time" "end_time").

Cancelling NSJSONSerialization - Search as you type, requests overlapping

Similar to the iPhone Facebook app search function, I am implementing search as you type functionality into my application although I have a problem when decoding the data into JSON format.
Basically what happens is because some searches take longer than others, they return at different intervals and this causes some small visual issues when the data is presenting on the screen.
I have set an NSLOG after each decode using NSJSONSerialization for the keyword 'industry'
2013-04-09 23:38:18.941 Project Name [42836:1d03] http://fooWebAddress/json/?method=search&limit=10&q=indus
2013-04-09 23:38:19.776 Project Name [42836:3e07] http://fooWebAddress/json/?method=search&limit=10&q=indu
2013-04-09 23:38:20.352 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=indust
2013-04-09 23:38:21.814 Project Name [42836:4e03] http://fooWebAddress/json/?method=search&limit=10&q=industr
2013-04-09 23:38:23.434 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=ind
2013-04-09 23:38:24.070 Project Name [42836:7503] http://fooWebAddress/json/?method=search&limit=10&q=industry
As you can see it is all out of order.
Does anyone have any way of stopping NSJSONSerialization for the previous connection.
Or possibly any other way to go about this problem?
Steps up to NSJSONSerialization...
NSURLRequest (initwithURL)
NSOperationQueue
NSURLConnection (asynchronous)
NSJSONSerialization
Thanks in advance.
When the user starts typing more text, you could cancel your previous connections and ignore any further delegate callbacks you receive from them. Then make the new request for the current text.
You can do this by maintaining some sort of lastRequest or lastOperation reference. When the user starts typing, call [self.lastRequestOrOperation cancel] and ignore any further notifications from that request with a check like if (request != self.lastRequest) { return; } in whatever callbacks you have.
However this has the problem that if the user keeps typing for a while you are constantly cancelling requests and they may not see any results until they have stopped typing.
A better solution would be to add sequencing so that each request is associated with an increasing sequence ID. You then only parse the result and update the UI when the sequence of the response is higher than the last one you received. If you receive any out-of-band responses from earlier, you just ignore them.
This is a much more complex issue than just being able to cancel the NSJSONSerialization. My suggestion is to use NSFetchedResultsController to populate your table view that shows the search results. Use the search term as one of the predicate variable in the NSFetchRequest attached to NSFetchedResultsController. And then, when you parse the results using NSJSONSerialization, store the results with the search term associated with that request. As soon as the search term changed (which you can detect when the user types more characters), re-create the NSFetchedResultsController and reload your table view. In addition, you can also try to cancel the call to parse the previous results if you launched it using performSelector:withObject:afterDelay. Beware that this cannot be always relied upon as the call may have been initiated by the time you are trying to cancel.
Kinda basic, but you could always maintain an nsdictionary of sub-classed NSURLRequests (sub-classed to provide a tag).
Start request - add request to dicationary with tag = array.count - 1, with key matching tag
Connection returns - is the request the most recent request, if so, parse json
Parse JSON - is the request the most recent request, if so, show results, if not, only display if there are no previous results displayed
Request handling - remove key from dictionary
most recent request = does the dictionary contain an object with a higher key value
Currently what you are doing is, you type each character and calling web-service. Why to call web-service for each letter you type. If user is type continuously, then it will increase the load, so call the web-service only when user stops for a particular interval of time. and then pass that string to call web-service or what ever method you are calling.
[NSObject cancelPerformSelectorsWithTarget:self]; // This will cancel your all req which is going to make when user typing without stopping
[self performSelector:#selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; // This will pass the string to call a web-service method, on which user hold for some time.

Resources