handling non-standard ext js grid-server comunication - extjs

The ext js (v4) grid I have receives collections of json records at any given time, where each record has a tag on it that tells the grid the operation to perform alongside other attributes. For example, in an incoming collection a grid might encounter the following (with the id being the key):
{"records":
[{"id":"101", "name":"I'm new", "op":"create"},
{"id":"102", "name":"I'm old", "op":"delete"},
{"id":"103", "name":"I'm different", "op":"update"}]
}
I'm trying to write the code to tell the grid or store to perform these various operations on the models, but to not have that operation then post back to the server (after all, that's where the directive came from). Simply put the client grid should represent what's on the server, where the objects can be popping in and out of existence.
I've looked into the readers and writers for proxies, or inheriting from the json proxy itself and modifying the read/write behavior, but it seems as though I'd still need to call the destroy/create/update commands on the models themselves and then somehow short-circuit the model behavior so they don't send that crud operation back to the server. None of these options feel quite right, however.
Is there a ext-js component I should be using in this case instead of the proxy/read/write objects?

You are over thinking this.
You don't need to send operations back to the grid. If your server sends a new set of data with a missing record (deleted) it will not show up in the grid. If you send a changed data set to the grid (write) those changes will just show up. And if you add record on the server side and send the set to the grid - a new record will show.
Basically if your server side drives all of the changes then you don't need the writer config and just have the read only grid.

Related

Data-aware controls are "empty" after closing, reopening datasets and TDatabase

I recently updated an old Delphi project to separate the creation of its data module and opening of that module's TDatabase, TTable and TClientDataSet components from the creation and showing of the app's form. Now, the app can toggle on and off the data components of the app. This new capacity isn't critical of course, but is "nice to have." My tool chain is RS v21 (the marketing version 10.4.1).
Yet there's a problem: after closing and reopening the data components from the UI, data aware controls show no data. Tests show that the underlying tables are open, can be navigated, and field values can be retrieved programmatically.
I've also established that resetting a data aware component's DataSource restores its display of underlying field data.
NB: data aware controls' DataSource are set at design time and, at run time after closing and reopening data tables, are not nil.
I conclude that resetting DataSource has a side effect -- probably tickling the DataLink within.
You can imagine I would like a means to obviate the need to reset a whole bunch of DataSources. The easy hopes that TDataSet methods like Refresh all fail. ;-)
A sketch of the coding inside the app's form looks like this -- to open:
dm:=Tdm.Create(nil);
dm.OpenDatabase;
dm.OpenDataTables;
And closing is the reverse:
dm.CloseDataTables;
dm.CloseDatabase;
dm.Free;
dm:=nil;
In the database Tdm: In design, the datasets are not active, and the database is not connected. Tdm.OpenDatabase envokes Open on the TDatabase; Tdm.OpenDataTables runs through the needed tables using their Open method. Tdm.CloseDatabase and Tdm.CloseDataTables are symmetrical.
Thank you for any insights.

Oracle ADF: Refresh Form data

I am developing a web app using Oracle ADF. I have a bounded task flow. In that I have a search page like below.
I have created the above two forms using view object data controls.
Searching is performing well. But my problem is when I go some where else in my application using menus provided left side and come back to the search page , the page is not getting refreshed. I am getting a search page that contains old search results. At this point of time if I am trying to make any changes am getting some error called "Another user with this id already modifed data ....". After this error my app is not running. Means what ever am trying to do its showing the same error.
So I need to make this: "When ever the user come to this form, He should get fresh form. It should not contain old search results.
Please help me. How do I achieve this.
Thank you.
There are 2 ways of doing it:
1) Set your task flow as ISOLATED, from Task Flow Overview tab -> Behaviour -> Share Data Control with calling task flow -> unchecked (or isolated, if you are using JDev 12c)
This will ensure you always start FRESH when accessing the page, but it will potentially create a performance overhead because entire View Object cache will be recreated (requeried) on page load. Nevertheless, it is the quickest solution.
2) You may create a default Method Call Activity in your task flow from where you may call a AM's custom method that resets the view criteria. The method will be placed on application module's implementation class and it may look like this:
public void initTaskFlow() {
this.getViewObject1().executeEmptyRowSet();
}
This will clean the result data. If you want to reset the querying parameters as well, you can use this example:
http://www.jobinesh.com/2011/04/programmatically-resetting-and-search.html
When you made any changes to any viewObject then excute this viewObject to match entity state and viewState , i think excuting viewObject will solve your issue
Ashish

Seamless Integration with REST API

Many examples on the net show you how to use ng-repeat with in-memory data, but in my case I have long table with infinite scroll that gets data by sending requests to a REST API (scroll down - fetch some data, scroll down again - fetch some more data, etc.). It does work, but I'm wondering how can I integrate that with filters?
Right now I have to call a specific method of API service that makes a request based on text in "search" input box and then controller updates $scope.data.
Is it possible to build a custom filter that would do that? And then my view would be utterly decoupled from the service and I could declaratively tell it how to group and order and filter data, regardless if it's in-memory or comes from a remote server, server that can serve only limited records at a time.
Also later I'm gonna need grouping and ordering as well, I'm so tempted to download the entire dataset and lock parts of the app responsible for grouping, searching and ordering (until all data is on the client), but:
a) that dataset is huge (hundred thousands of records)
b) nobody wants to deal with cache invalidation headaches
c) doing so feels so damn wrong, you don't really expect me to 'keep' all that data in-memory, right?
Can you guys point me to maybe some open-source examples where I can steal some ideas from?
Basically I need to build a service and filters that let me to work with my "pageable" data that comes from api, like it's in memory-data.
Regardless of how you choose to solve it (there are many ways to infinite-scroll with angular, here is one: http://binarymuse.github.io/ngInfiniteScroll/), at its latest current beta version, ng-repeat works really bad with large amount of data - so do filters. The reason is obvious - pulling so much information for changes is a tuff job. Moreover, ng-repeat by default will re-draw your complete list every time something changes.
There are many solutions you can explore in this area, here are the ones I found productive:
http://kamilkp.github.io/angular-vs-repeat/#?tab=8
http://www.williambrownstreet.net/blog/2013/07/angularjs-my-solution-to-the-ng-repeat-performance-problem/
https://github.com/allaud/quick-ng-repeat
You should also consider the following, which really helps with large amounts of data.
https://github.com/Pasvaz/bindonce
Updated
I guess you can't really control your server output, because filtering and ordering large amount of data are better off done on the server side.
I was pointing out the links above since even if you write your own filters (and order-bys), which is quite simple to do - http://jsfiddle.net/gdefpfqL/ - (filter by some company name and then click the "Add More" button - to add more items). ordering by is virtually impossible if you can't control the data coming for the server - the only option is getting it all, ordering and then lazy load from the client's memory. So if each of your list items doesn't have many binding by it self (as in the example I've added) - the list item is a fairly simple one (for instance: you simply present the results as a plain text in a <li>{{item.name}}</li> then angular ng-repeat might work for you. In this case, filters will work as expected - say you filter by searched text:
<li ng-repeat="item in items | filter:searchedText"></li>
even for new items added after the user has searched a text, it will still works because the magic of binding.

Keeping repository synced with multiple clients

I have a WPF application that uses entity framework. I am going to be implementing a repository pattern to make interactions with EF simple and more testable. Multiple clients can use this application and connect to the same database and do CRUD operations. I am trying to think of a way to synchronize clients repositories when one makes a change to the database. Could anyone give me some direction on how one would solve this type of issue, and some possible patterns that would be beneficial for this type of problem?
I would be very open to any information/books on how to keep clients synchronized, and even be alerted of things other clients are doing(The only thing I could think of was having a server process running that passes messages around). Thank you
The easiest way by far to keep every client UI up to date is just to simply refresh the data every so often. If it's really that important, you can set a DispatcherTimer to tick every minute when you can get the latest data that is being displayed.
Clearly, I'm not suggesting that you refresh an item that is being edited, but if you get the fresh data, you can certainly compare collections with what's being displayed currently. Rather than just replacing the old collection items with the new, you can be more user friendly and just add the new ones, remove the deleted ones and update the newer ones.
You could even detect whether an item being currently edited has been saved by another user since the current user opened it and alert them to the fact. So rather than concentrating on some system to track all data changes, you should put your effort into being able to detect changes between two sets of data and then seamlessly integrating it into the current UI state.
UPDATE >>>
There is absolutely no benefit from holding a complete set of data in your application (or repository). In fact, you may well find that it adds detrimental effects, due to the extra RAM requirements. If you are polling data every few minutes, then it will always be up to date anyway.
So rather than asking for all of the data all of the time, just ask for what the user wants to see (dependant on which view they are currently in) and update it every now and then. I do this by simply fetching the same data that the view requires when it is first opened. I wrote some methods that compare every property of every item with their older counterparts in the UI and switch old for new.
Think of the Equals method... You could do something like this:
public override bool Equals(Release otherRelease)
{
return base.Equals(otherRelease) && Title == otherRelease.Title &&
Artist.Equals(otherRelease.Artist) && Artists.Equals(otherRelease.Artists);
}
(Don't actually use the Equals method though, or you'll run into problems later). And then something like this:
if (!oldRelease.Equals(newRelease)) oldRelease.UpdatePropertyValues(newRelease);
And/Or this:
if (!oldReleases.Contains(newRelease) oldReleases.Add(newRelease);
I'm guessing that you get the picture now.

Retrieving common data on different forms

Lets take an example of WinForms applcation and making invoice. On the Invoice form we retrieve a list of products, so the user will be ale to pick products for current invoice. Lets also consider that during this process user realizes that he needs to add a new product (or edit current) to ProductList before he can place it in invoice. So he opens a ProductForm where all the products are retreived (again).
It could also be in opposite order, that user first edits Products, and then without closing the Products Form, opens new Invoice. The principle is that data is two times loaded, and effectively its the same data.
What is the propper way to handle this scenario, so we can tell one form that data is already loaded, and to retrieve that data from memory? And when all the consumers (Forms) of the data are closed, then also the data should be released from memory? Or I am going in wrong direction, and there is a better way?
Thanks,
Goran
Definitelly go with data loaded "twice" or you will introduce much worse problems.
Sharing data means sharing ObjectContext. Even in WinForms application this is considered as bad approach. Check this article (it is about NHibernate but the description is valid for EF as well).
The problem is that ObjectContext is unit of work. If share context between two windows you can easily get into situation where you modify data in first window (without saving them!) and you continue in second window where you push save button but it will save data from both windows! You can't selectively save data only from one window when you share the context.
If the Controls that are using the data are all child controls of a shared Parent control, then you could just pass around the datacontext, so that they all shared the same datacontext.
However, the general use case with databases, which is what backs EF in most cases, is to read the data in each time that it is needed.
A solution to this if as you say you already have the item being used in one form is to just take a Refrence to that item into your new form.
So in the case Where you have an invoice which has a Product List and you want to add to the product list, you could pass the product list from the invoice to the opening product list.
There are some issues with this:
If another user changes the datasource while one has opened it (a.k.a. Concurrency)
Handling save don't save scenarios where they may have made a change in one area that they don't actually want added to the data.
However, unless it is a true performance issues, I would just load the data every time. You can simplify this a lot by using the repository pattern, so you can just call a single method to get a list of products or an invoice, or whatever part of data you need.

Resources