Backbone - Get Router parameter and reload same route - backbone.js

I have a table and I'm deleting a row. When I delete this row, I want to reload the current Backbone route, but few things to take in count:
e.g I'm in this route
"oneurl#order-by-name/page-8"
If the table, at that page, has only one record and I delete it, I would like to redirect to #order-by-name/page-7, so I need to get the "page" parameter. If there are still records, I want to "reload" the same route (to add next page's row if there are). It seems is not possible (https://github.com/jashkenas/backbone/issues/1214).
Any ideas?

As discussed in the issue you link (mainly jashkenas's comment "trigger: true is usually a code smell"), you shouldn't really be using routes like that for a javascript application.
What you should be doing instead:
have somewhere to store the current application's state (e.g. a plain javascript object) which is passed to the function taking care of displaying the views and data you want
when a row is deleted, modify the application state object (e.g. changing the current page attribute) and call the same function as above, once again passing in the configuration
update the url with navigateonly if the fragment should change
In reverse, your router should parse the url fragment to generate a configuration object discussed above, and call the function to render the views (passing in the configuration info).
For more on how to manage routing without using trigger: true everywhere, take a look at http://lostechies.com/derickbailey/2011/08/03/stop-using-backbone-as-if-it-were-a-stateless-web-server/ and the free preview to my book (on Marionette, but the same applies to Backbone) which also contains a chapter discussing route handling.

Related

ReachRouter navigate in component constructor

If a user goes to a page that requires a context beyond what's on the url, I'd like to redirect them elsewhere. The use case is:
/todos/list - this page shows the user their list of todos. It contains links to:
/todos/edit?id=1 - this page allows the user to view/edit details about a particular todo.
If a user were to go directly to /todos/edit (with no id), I'd like to redirect them to /todos/list. I have tried doing this via navigate('list') conditionally in the constructor. This does update the browser url correctly, but it doesn't render the /todos/list page. Is this possible to do? Or is this not possible to do the para below?
I understand the more common url would be /todos/edit/1 so that reach router would handle my issue w/out me needing to deal with it. However, I'm just using this as an example of a piece of information required to render the page that isn't necessarily part of the the url path.
of course as soon as I type the question in stackoverflow, I find the answer is in the docs right in front of my face:
https://reach.tech/router/api/Redirect

Render AEM pages in React dynamically independently of URL path

I have the need to be able to render any of the pages in my AEM model.json dynamically regardless of the current URL in a SPA React app.
My AEM model.json structure has pages following the /<country>/<language>/rest/of/path format, but I want to be able to strip the country/language and just use the rest of the URL path.
I am able to do this when I initialize the ManagerModel with a the desired path like this:
const path = `/path/to/<my_model>.model.json`
/* initialize the ModelManager with the path to the model.json */
ModelManager.initialize({ path })
/*
grab the desired section of the model and render by calling ReactDOM.render
By doing this I am able to render the section of the model that maps /us/en/user-account` for
example, and render the correct content even though the current browser path is `/`
*/
ModelManager.getData(`/us/en/<page_to_load>`).then(render)
When I handle navigation with history.push (I use react-router), I want to be able to render another page following the same logic. By default, having executed ModelManager.getData("/us/en/<page_to_load>"), every page that I navigate to then renders that same portion of the model.
To fix this, I have tried many variations of ModelManager.getData() calls with no success. The only thing that I have been able to have any success with is dynamically passing the path to the next page to render to a callback function that is defined on the index.js level and passed down as a prop to App.js. The callback triggers another ReactDOM.render call and loads the page correctly regardless of what the actual URL path is. That code looks something like this:
<App
reRender={(path) => {
/* manipulate the path so that it properly maps to the correct AEM model data */
const updatedPath = `/us/en/${path}`
/*
this works, but causes another ReactDOM.render call every time that the current page is
changed
*/
ModelManager.getData(updatedPath).then(render)
}}
/>
There are also cases where the page that has been navigated to doesn't have a corresponding path in the modelStore mapping. I am able to handle that like this:
const pathToInsert = `/<country>/<language>/${window.location.pathname}.model.json`
ModelManager.modelStore.insertData(pathToInsert)
ModelManager.getData(pathToInsert).then(render)
/*
I have been having issues with this, but can get the newly inserted model to load properly by
re-routing back to the current path from the current path
*/
this.props.history.push(window.location.pathname)
I have read and re-read the documentation here and I am unable to figure out the correct way to do what I want to do. The above solutions work for the most part, but are pretty hacky and I would like to find out the proper way to accomplish this. Any help is greatly appreciated!
Yes, I found a work around solution. The AEM library can't handle this requirement out of the box unfortunately. My solution was to make a wrapper for my App component. In that wrapper I initialize the model manager, clone the data and store it in local stage. Then you can conditionally modify the model and pass it along as a prop to your App component. If you have a good understanding of how AEM model data is mapped you should be able to figure out a way to display what you want. You can also fetch and insert models into your master model's ":children" prop (think that is the field name, have not looked in a while).

React Router setup for 'unlimited' params

I am trying to implement the React Router in such a way that it supports a route like this:
/myPages/:pageName1/:pageName2/:pageName3/...
The idea is that, even though the page being rendered is only the last page, the pages are nested, and the depth is not something that is pre-determined. The component that renders the actual page needs to know the names of parent pages.
To clarify, the idea is that the page data in the backend are in a tree structure in such a way that, in the above example, page1 is the root page, page 2 is a child of page1, page 3 is a child of page2, etc. In addition, one page can have multiple children. The last child name (so pageName3 in the example) is what is being used to query the database and get all the content required to render the full page. The parent names are required to render navigation-related subcomponent. I should also mention that just having /myPages/:pageName3 and getting all parent names from the backend is not really an option. I could fetch that information from the backend, but the URL presented to the user still needs to have that structure.
I am hoping that there's a way to get this type of information as an array, but I am having a hard time finding an example like this on the web.
maybe this can help.
https://github.com/ReactTraining/react-router/blob/d28d46dce08a5756a085f7e5eebb5169ea59e40b/packages/react-router/docs/api/Redirect.md#from-string
states:
A pathname to redirect from. Any valid URL path that path-to-regexp#^1.7.0 understands.
maybe you can combine
<Redirect from='/users/:id' to='/users/profile/:id'/>
with
var re = pathToRegexp('/:foo+', keys)
(taken from https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#one-or-more)
then you'll end up with
<Redirect from='/:pageName+/:id' to='/:id'/>

Angular UI Router - any way of referencing the same url variable more than once?

I would like to implement finite netsing of ui router states (it is required by the client), the maximum depth of nesting can be a fixed value (for example 10) therefore i would like my states to look as such:
.state('page',{url:'page/{pageName}',templateUrl:...)
.state('page.page',{url:'/{pageName}',templateUrl:...)
.state('page.page.page',url:'/{pageName},templateUrl:...)
etc...
In the end i would like for user to be able to enter urls like:
'/page/page1/subpage1'
'/page/page2/subpage1/subsubpage2'
'/page/page3'
etc...
The obvious problem is that ui router will overwrite the 'pageName' variable for each (sub)state, therefore after navigating to /page/page1/subpage1 i will only have {pageName:'subppage1'} variable set in state 'page' and 'page.page'.
In the whole application the ui-sref would only use the RELATIVE states so when i am in the 'page' state i would go into 'page.page' state and so on. I would like to be able to move the html view of the page up or down the state hierarchy as needed, and i would like not to change every ui-sref call in such case (right now i would have to change the variable name because it has to have different name in every state)
Is there any possibility to achieve my desired scenario? i have tried defining 'pageName' as an array type, but it does not seem to work (gets overwriten for every substate). Using custom ui router type also seems to not work since it cannot modify stateParams objects, only returns the representation of single url value (therefore the 'pageName' is also overwritten).
Ui-router extras also seems not to help here, or maybe i am missing something.

Prevent deep link in react-router

In my application I'd like to have certain portions of the app not be able to deep linked to. For example our users have a list of surveys and I'd like if someone tried to go directly to a particular survey directly such as /survey/1 that react router would pick up on this and immediately redirect them back to /survey and they would have to select the one they want. I've tried to write onEnter hooks but they seem to be very cumbersome since the only way I've been able to get them to behave correctly is to store some global state that says they have been to the main page and inspect that every time the route is navigated to.
Im using pushstate in my application if that makes any difference and react-router 2.0
I'd like to try to avoid having to write server rewrite rules for this since there are a lot of areas in my application where this rule is applicable.
I have a suggestion which is similar to the onEnter hook:
Wrap the component of the survey/:id route with a function which verifies if deep linking is allowed or not, let's call this function preventDeepLinking
The preventDeepLinking function checks if the location state contains a certain flag, let's say allowDeep. This flag would be set in the location state when navigating from another page of your app. Obviously, this flag will not be set when the user tries to navigate directly to the page of a survey.
The preventDeepLinking function will render the wrapped component only if deep linking is allowed, otherwise will redirect to a higher route.
I created a sample on codepen.io. You can play with it in the debug view of the Pen: http://s.codepen.io/alexchiri/debug/GZoRze.
In the debug view, click the Users link and then on a specific user from the list. Its name will be displayed below. Notice that its id is part of the url. Remove the hash including the ?_ and hit Enter. You will be redirected to /users.
The code of the Pen is here: http://codepen.io/alexchiri/pen/GZoRze
The preventDeepLinking function can be improved, but this is just to prove a point. Also, I would use the browserHistory in react-router but for some reason I couldn't get it running in codepen.
Hope this helps.

Resources