How to build Observable from dynamically created and destroyed sources? - rxjs

My question is similar to this one RXJS: Single Observable from dynamically created Observables (no answer there).
I want to parse some pages continuously. There is the main page where I can get a list of links of pages to parse. This list of links changes over time. Then I follow the links and parse the pages continuously as well until their link disappears from the main page and start parsing new pages as they appear on the main page.
My setup for now is as follows. I have a class that given a url can return an Observable of continuously emitting items (parses a single link from the main page). This works great. However, I want to have a "master" class that will be able to return an Observable of same items but taken from multiple pages. The problem that I have is the list of pages is changing (and so is the list of underlying Observables and I can't just use Observable.merge.
TL;DR:
I have multiple Observables that I want to merge. But this list of Observables is changing dynamically and I don't know how to handle this.
How can I approach this?

If you already have Observable of "main" page, and a function to fetch items based on this data. You can use switchMap operator for "switching" this dynamically changing list, something like:
getMainPages().pipe(
switchMap(main => getItemsFromMultiplePages(main))
)
where:
getMainPages() - return Observable of main page data
getItemsFromMultiplePages(main) - return Observable of items, created by combining(maybe using merge) data from multiple pages

Related

ApolloClient - run multiple async requests with different input/variables - something like React-Query's useQueries

Apologies if I've just managed to miss it in the docs, but I can't find a way to do this in Apollo Client.
I've read about query batching, but this in fact the opposite of what I want to do. I want my queries sent as separate isolated queries.
Happy to expand on details if needed, but I think the title says it all.
so, my solution has been to create a new component that
returns null (i.e. renders nothing)
runs a useQuery and puts the result into an array (who's setter is passed in from the parent)
This new component sits inside a loop that iterates all my different variable sets that I want to fire the query with.

How to get the result of a asynchronous action in NGXS?

I want to perform an action based to the result of an asynchronous NGXS action.
In a Angular frontend app I'm using NGXS for state management. Some of the actions involve talking to a backend via REST calls. Those actions are implemented as asynchronous actions, with the reducer functions in my state classes returning an Observable.
What I'm looking for is a way to get hands on the result of the backend call, to be able to perform some action.
One use case I'm trying to implement is navigation to just created objects: Business objects are created in the frontend (Angular) app with a couple of domain properties. They get persisted in the backend, and as a result an ID for this object is created and returned to the frontend, and incorporated into the NGXS store. As a direct response to this, I'd like to navigate to a detail view for the new object. To do so, I need
(a) the information that the call has been returned successful, and
(b) the answer from the backend (the ID in this case).
Another slightly more complicated use case is the assignment of a number of tags to an business object. The tags are entities by themselfes, and have an ID each. In the UI, the user can either pick existing or add new tags. Either way, multiple tags can be added in a single step in the UI, which means I have to
call the backend for each new tag to create the ID
after all missing tags are created, update the business object with the list of tag IDs
In general, there are use cases in the frontend that depend on the result of a backend call, and there is no clean way to find this result in the store (although it's in there)
I know I can subscribe to the Observable returned from the store's dispatch method (as shown in asynchronous actions).
I also know about action handlers. In both cases I can attach code to the event of an action finished, but neither option enables me to get the result of the backend call. In the fist case, the Observable carries the whole store, while in the latter case I get the original Action, which is unfortunately missing the essential information (the ID).
The part you're missing here are selectors. Dispatching actions is not supposed to give you back a result. The only purpose of the Observable returned by store.dispatch() is to tell you when the action's handlers are done.
To get to the data returned by your calls to the backend, you have to patch the state inside your action handler. And then, outside of your state, you can access the data using store.select() or store.selectSnapshot() depending on what you need. Your state class should look somewhat like this (untested):
#State()
export class SampleState {
#Selector(SampleState)
sampleSelector(state) {
return state.sampleObject;
}
#Action(SampleAction)
sampleAction(ctx: StateContext<any>, action: sampleAction) {
return sampleBackendCall(/* ... */).pipe(
tap((result) => {
ctx.patchState({ sampleObject: result });
})
);
}
}
Now you can access this result where ever you need using the Store. For the use case of navigating to an element after its creation, you can combine a subscription to store.dispatch() with a store.selectSnapshot() like this:
store.dispatch(new SampleAction()).subscribe(() => {
navigateTo(store.selectSnapshot(SampleState.sampleSelector));
});
Note that in this easy case a selectSnapshot is perfectly fine, as we only want to get the value we just finished writing into the state. In most cases though, you will want to use store.select() or the #Select() decorator because they return Observables which enable you to also correctly display changes in your state.
That said, I'd like to add that if saving data inside the state is not necessary for you at all, then probably NGXS is the wrong library for you in the first place and you could as well just use an ordinary angular service directly returning the result of the backend call, like suggested in the comments.

react-admin - Forget list filters after redirection

With react-admin we can filter lists results.
When going on another page, and going back to the list, previous filters are still applied. (A strange point is that filters don't appear in URL hash)
Demo:
https://marmelab.com/react-admin-demo/#/
Is this a react-admin or redux behavior?
I want to have a fresh result list each time I load it.
I have two ideas to do it:
I know children of <List/> receive a setFilter function in their props. Maybe I could call setFilter({}) in method componentWillUnmount() of each child (<Datagrid/>)?
Call react-admin action changeListParams() in each componentWillUnmount() of my list modules.
Is there a better solution? I can't believe the amazing team building this awesome framework didn't think of this use case!
Thanks!

How to load the jqgrid in a selector with context

In general we call the jqgrid as in$("#grid_loc").jqGrid({});
But i want to specify the context like $("#grid_loc",context).jqGrid({}). But this is not working. Can somebody help in this?
I have to load server side data using url option.
Infact i occured to have this, as i have tabs on my page.
In each tab, i have to have a jqgrid, not different grids but same grid with different data .
Here i am getting the tab context using var tabset = $("div.tabset");
newdivid = $("div[class*='active_tab']",tabset).attr("id");
var newmenudivid = $("#"+newdivid);
And
the grid code as
$("#grid_workflow", newmenudivid).jqGrid({....});
I have been trying to find out a way to do this. you can find some of my effort in the comments section of the link
how to develop same jqgrid in multiple tabs
i was successful with id overwriting for the same purpose. But that is not a good way though. So i am forced to have another approach ie. context
I suppose that you misunderstand some important things which corresponds to id attribute. The most important that all elements on the page having id attribute have to have unique value of the attribute. In other words the ids have to be unique over the whole HTML page.
So if you need create for example tree grids inside of tree tabs you have to define different id attributes for every grid. For example; grid_workflow1, grid_workflow2, grid_workflow3. If you create the tabs and grids dynamically then you can have some variable in the outer scope (for example global variable) and increase the value of the variable. You can construct id of the grid using some prefix (like "grid_workflow") and the value of the variable. In the way you can create multiple grids with unique ids. Many JavaScript libraries uses the way to generate unique id attribute. Ij you want you can use $.jgrid.randId() method which will returns you unique strings which can be used as ids.
Because of the syntax $("#grid_workflow", newmenudivid) you should understand one important thing. I would recommend never use it. The reason is very easy. It could help only if you have id duplicates. In all other cases if will works exactly like $("#grid_workflow") but slowly. The reason is easy to understand. Web browser hold internally the list if all ids on the page and if you use getElementById method directly of indirectly (in $("#grid_workflow")) the searching of the element with the required id will be like searching in the index in the database. So you will have best performance results. If you use $("#grid_workflow", newmenudivid) then you don't allow web browser to use the index of elements by id. So the usage of context will follow to slow searching throw all children elements of newmenudivid. So you should avoid usage of jQuery context with id selectors.

Jquery/Ajax/HTML assistance needed

I am trying to build a very basic message center. My idea is to use Jquery to make an ajax call to a classic asp page that will build a Json array.
I then plan to use Jquery to grab that Json.
My main questions currently are:
Is it possible to empty out a multi select input list?
Would it be better to not use the input at all and build a nifty Jquery list?
Will using Ajax allow me to on the fly empty this list; replace with with different information and/or append items to this list all without a page refresh?
I need to be able to allow the client to select multiple people from this list. Is my outline above feasible?
Is it a good way to achieve what I am looking for?
I have very little experience with Json and Ajax, and was hoping someone could confirm if it was possible before I dive in.
Is it possible to empty out a multi select input list?
Yes
Would it be better to not use the input at all and build a nifty Jquery list?
You can have this work with any kind of element, including a standard input.
Will using Ajax allow me to on the fly empty this list; replace with with different information and/or append items to this list all without a page refresh?
Yes, in a function that handles the response of the Ajax call and uses call's result to populate the list. Since you're using Ajax, the call is asynchronous so the entire page will not be refreshed as a result of your call.

Resources