So we are creating different pages for our application and we need to route from one page to another everytime. We are working on Next.js.
Problem - Say, we have a Home page. From this home page, we can either route to pageA, and the pageA will show different data or different form based on the query parameter passed in the routing, and we need to keep passing that query parameter to upcoming pages to maintain that journey.
Now, as I can see, the usage of query parameter is getting a bit complicated as the application is growing.
I would like to know if there is any other way to do routing where we can skip the usage of query parameter and still maintain the state.
If the query parameter is sent to many subpages, you can use localstorage (or sessionstorage). On the page mounting, you can get the values inside localstorage and set them on the hydration phase.
Using localstorage is as safe as query params. With localstorage, it will be easier for you to send values to sub-routes. If you only have one or two sub-routes, query params are ok but with more sub-routes, the code logic / maintainability could be annoying (especially because you want to always send the same query params to sub routes). With localstorage, you can also create a custom hook to get the values / update the value into multiple components.
Just as a reminder, don't store any sensitive data inside localstorage. I recommend you to read the new Next.js routing system too ! (breaking changes) Read it here.
Related
I am building a library for listing products in a web application. It has to have filter, search and sort features. I have a web service that when called with filter, search and sort parameters can return the result set with all the those parameters applied. If page number is passed along with that, with number of products per page, it can return that specific page as well. It looks very much suitable to have the data populated through AJAX at client side using this web service. However the page will lose all the parameters (filter, search & sort) when clicking back button and coming back and the page will display the default list of products, as the URL will remain the same as below, irrespective of the filter or page or search or sort parameter
<domain>/productlist
. To retain them, I have to save these in sessionStorage or any other such mechanism. Will this be a violation of REST principles? Do I have to avoid AJAX and have the parameters always passed in the URL for the actions to be repeatable and abide by REST principles like
<domain>/productlist?filter=f1f2f3&search=apple&sort=price&order=1&page=3&items=10?
I may be wrong in understanding REST as well, as I am a bit new to this. So would like to understand better to have a proper & compliant design.
To retain them, there should have some better approaches instead of putting those params into session storage; one of the approach would be for every AJAX requests, pushing the search params into the window.history via window.history.pushState function, once user go back to previous page, all you have to do is check whether urlParams is filled with something or empty, and fetch the data according to the urlParams.
REST is a concept that how you should handle the requests throughout the frontend and backend.
AJAX is a method of fetching data from backend.
They could coexist therefore you could use AJAX and at the same time abide the statelessness of REST.
I have product listing page, where I do have all data to show user, if user is applying filters, I am filtering list on client side itself using Angular 2,
Now if user move forward to project details page and click browser back button, all applied filters vanished as it should be, But I need to implement so that on back button all applied filters should persist.
Solutions I am thinking: -
Approach : Whenever User apply filter we add that in URL and redirect.
Problem : On every URL redirect API's will be called.
Is there a better way I can approach this problem ?
Storing things in the URL as arguments is a good approach, since you don't depend on hidden state (global application variables) to build your view.
However I'd not intercept the routing component, but rather use Angular's support for structured URLs and filter the data in the onInit method or whenever it is available.
If you want the filter criteria being visible in the URL (and to be bookmarkable) use router parameters and redirect to the URL containing the updated parameters. If you use routerCanReuse() { return true; }, then the component is not even reloaded but justrouterOnReuse()` is called where you can acquire the updated parameters.
If you don't want the filter criteria to appear in the URL, use a shared service to store the parameters, then navigating doesn't destroy the parameter values. Ensure that the provider for the service is provide high enough (AppComponent for example) for it to not get destroyed when a component gets destroyed by routing away.
I had a similar problem with the added condition that, I had to redirect the user back to listing page with the filters applied when he used the save functionality.
The approach I used was to combing both a service and having filters in the URL parameters.
The reason to use both is,
You could enter the product detail page in 3 ways:
From Product Listing.
Directly from URL.
From some other, where you might have given the link.
And so you cannot just use this._location.back(); as you might not want to redirect to the last page in all cases.
So my approach was to store the last URL in a service, and in the detail component check if there is any stored URL.
An important thing here is to check and pop the stored URL on the ngOnInit() as the user might not always click on save.
Attaching the code to the service, it's fairly basic.
#Injectable()
export class ReturnHistoryService {
private _returnURL: string;
saveReturnURL(returnURL: string) {
this._returnURL = returnURL;
}
popReturnURL() {
let returnURL = this._returnURL;
this._returnURL = null;
return returnURL;
}
`
Make sure the provider is not per component.
I'm using react-router and redux-simple-router in conjunction with server side rendering and when I navigate to a url like:
routeActions.push({ pathname: '/main', state: 'some_state'});
I want to be able to extract some_state from the request so I can render an initial redux state and send that back to the client. How do I extract the state from the request on the server side? Where does history and react-router put it?
This is particularly important for mobile because desktop, as I've tested, doesn't fire separate requests but mobile devices do which means the page reloads with a fresh initial state.
state corresponds to state in the History API - it's associated with the current location, but it's only available on the client, so it's not suitable for passing along arbitrary data if your app needs to support server-side rendering.
If you want it to be available on the server, you would need to make it part of the URL. perhaps as a query string.
Aside: location state is useful in other ways in isomorphic/universal apps, such as passing around POSTed form data to be handled using an onEnter hook, or for passing form data and validation errors to use a redirect transition to respond by rendering an invalid form in the same scenario.
I have a theory as to how to approach them, and was looking for some guidance on how to solve this problem and see if I am on the right path, because I am not sure.
I have a web app for a project I am building, and I have a database that I need to query for specific information. I have a search button that is attached to a function in my MainController, and I need to have my data passed on to my result.html file, which displays information from a ResultsController.
This is my theory for how to get this working using fake data, and an html request (which uses promises I imagine?)
for fake/test data, I stored an array with objects that represents JSON data in my services file that was basically the parent to ResultsController and MainController, and ResultsController would take in that information and display it on the screen.
For querying a database, my search function would search the database, and fill/replace the array in my services file with additional information. By virtue of changing that array of objects in my services, my results.html should pull down new data automatically when I click search, since the ResultsController has access to that same JSON data. (also, clicking search submits the query and then does $location.path("/results") after to get to the results page).
For querying a database and dynamically changing the information on a page, are these the right steps to submitting a request to a database in pulling information down upon each "search" request?
You are on the right track in using a service to share logic and data between the two controllers. This is generally seen as best practice - and it is better than the approach that is sometimes used of putting the logic and data in a parent controller, and using scope to access it in child controller.
The style guide linked to above is worth a read if you are looking for some guidance on best practice in setting up an angular app (https://github.com/johnpapa/angular-styleguide).
We're using DataTables as our table, and we're having a problem/disagreement with somehow keeping the history of filters that were applied to the table before, so that users can back/forth and refresh through these.
Now, one solution that was proposed was that I keep the filters string in the URL, and pass it around as a GET request, which would work well with back/forth and refresh. But as I have very customized filtering options (nested groups of filters), the filter string gets quite long, actually too long to be able to pass it with the GET request because of the length limit.
So as GET is out of the question, the obvious solution would be a POST request, and this is what we can't agree upon.
First solution is to use the POST request, and get the "annoying" popup every time we try to go back/forth or refresh. We also break the POST/Redirect/GET pattern that we use throughout the site, since there will be no GET.
Pros:
Simple solution
No second requests to the server
No additional database request
No additional database data
Only save the filter to the database when you choose to, so that you can re-apply it whenever you want
Cons:
Breaks the POST/Redirect/GET pattern
Having to push POST data with pushState (history.js)
How to get refresh to work?
Second solution is to use the POST request, server side saves the data in the DB, gets an ID for requesting the saved data, returns it, and the client then does a GET request with this ID, which the server side matches back to the data, returning the right filter, thus retaining the POST/Redirect/GET pattern. This solution makes two requests and saves every filter that users use to the database. Each user would have only a limited number of 'history' filters saved in the database, the older ones getting removed as new ones are applied. Basically the server side would shorten your URL by saving the long data to the database, like an URL shortening site does.
Pros:
Keeps the POST/Redirect/GET pattern
No popup messages when going back/forth and refreshing the page due to the post data being sent again
Cons:
Complicated solution
Additional request to the server
Additional request to the database
A lot of data in the database that will not be used unless the user goes back/forth or refreshes the page
A third solution would be very welcome, or pick one of the above and ideally explain why.
This is a fleeting thought i just had...you can save state of length, filtering, pagination and sorting by using bStateSave http://datatables.net/examples/basic_init/state_save.html
My thought was, theoretically you could save the cookie generated by datatables.js into a database table, like you mention in the second solution, but the request only has to happen each time you want to overwrite the current filter, replacing the current cookie with the previous "history" cookie