-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stopping tab change #19
Comments
There is some code for this in the
This would delay updating the tabs until a successful state change. Is this along the lines of what you were thinking? |
Yes, that seems to be along the lines of what I was thinking. However, it does not appear to be working. I have verified that the URL is NOT updated in the case that i am doing event.preventDefault() - this confirms for me that the state change has been stopped. Yet, the tab set is still visibly updated to reflect the tab that the user clicked on (prior to the event.preventDefault()) I think the problem is related to the fact that the $scope.go function calls $state.go directly. Either that or something lower level, perhaps in bootstrap tabs - not sure. |
Let me look into it, sounds like something easy to write a test for. |
Plunk is here: http://plnkr.co/edit/pGToXRrAOTxHlD3Ps5Rq .... (using version 1.3.0) |
Great thanks. It seems to work as you would want it to. It does not load the tab 3 content, tested in Chrome and Firefox. Not sure how I can help since it seems to work as intended. I just created a testcase for this (not checked in) which I will add to the specs in master (here it is to give you an idea):
|
Yes, it does not load the tab3 contents. BUT, it does render the tab 3 as selected. This rendering is the problem as the visual representation is now out of synch with the real data and the user is confused. The visual rendering should still depict the original tab that was selected before the click on tab 3 as selected (not tab 3 as it was prevented). Can you please take another look with this visual state in mind (this is not addressed by your test case). |
Ok so that's the only issue then. Forcing an update after
but i'm convinced you just want to disable the tab in certain situations. As luck would have it, I released BTW since you are using a custom template, for |
Hello and thank you. Unfortunately, I do NOT want to disable the tab in this case. The user is free to say that they want to continue to the newly chosen tab if they wish (and ignore their previous changes) - see use case description at start of this thread. In this case, the state change will succeed and the new tab (tab 3) should be visually selected). If I disable, then they will not be able to do any of this as they cannot initiate a tab change to the specific tab - not what I need in this case. I appreciate your code sample, but am unclear where I can place it in my code? It seems like it would need to be in your directive in order to have the proper scope? I have attempted several ways to work around this visual issue without success, so I will appreciate a fix for this issue in the directive (or a clear example how to handle in my code), please. |
In that case why can't you use your custom template |
The reason I am using the $stateChangeEvent based approach is because I need to apply globally within the app - not only for tab navigation, but also for page-to-page navigation outside of the tabs. I am working on a directive that is intended to be general purpose for detecting potential unsaved changes, notifying the user and allowing them to choose next steps (i.e. cancel or continue/ignore) - all triggered by a stateChangeEvent. Additionally, the fact that I am using a custom template is coincidental in this case - but not in all cases I have, so the ng-click approach will not work in all cases. If you agree that cancelling the state change should revert the active tab, then how do we get to that behavior? |
Unfortunately there is no |
How about adding logic in the directive to detect that the active tab has been changed to something other than it should be an reverting it accordingly? This could be done regardless of any UI Router constructs. |
Here is my present workaround ... I'm sure there must be a better way and am open to your suggestions/improvements! In the $scope.go function, I added a check after a small timeout (needed to allow the state transition to complete (or not if cancelled)....
This seems to keep the tab visual state correct in my testing so far. Looking forward to your thoughts and input. BTW, this is with the 1.4.0 version. |
That will never work if there are any async resolves on state change. I can see you are very keen to solve this issue :) What about manually triggering a See http://plnkr.co/edit/sXTMQT82B69gzW0thKvW IMO |
Indeed, I am keen to solve this issue. Thank you for both your assistance and this useful directive! I share your opinion that a ui-router $stateChangeCancel would be helpful for these purposes. Not sure if you have any connections there, but it may be worth running by them to see if this has been requested before or could be easily added? While I understand your perspective and proposed solution, I would prefer something more along the lines that I proposed (i.e. fully encapsulated in the directive) for the following main reasons:
What would you think about evolving the original approach I suggested into a watch based algorithm instead of the delay)? This would keep the logic entirely encapsulated in the directive, address your valid concern about async resolves (although I am honestly not really clear on the order of execution there - i.e. would resolves actually continue once the event is cancelled vi preventDefault?) and keep the use of $stateChangeError clean for its intended purposes. I'm also always cautious adding watches as this can have adverse performance impacts when used in excess. However, in this case the addition of a single watch seems to me to be worth if relative to the other potential trade offs we are considering. Looking forward to your thoughts. |
Actually, I just had a chance to do some testing here. It appears that async resolves are NOT even triggered if you event.preventDefault() in the $stateChangeStart. Based upon this and the above comments, I still prefer my original approach. What are your thoughts given that there is not an issue created by it for resolves? |
Since this directive is based on I'll take a further look to see if I'm very mindful of not solving one special use case at the expense of all others - but if either of these are flexible enough to work I'll concede. |
In my testing setTimeout(..., 0) works and does NOT invoke async resolves when cancelled. |
Ok, Take a look at the plunkr here: http://plnkr.co/edit/sXTMQT82B69gzW0thKvW If this is a suitable workaround i'll release it, with a view to using |
Great news about $stateChangeCancel! That will be useful for these as well as other purposes. I like your workaround. It appears to work and serve the purpose until $stateChangeCancel lands. Please let me know which version will have this workaround in it. |
Any updates here on the workaround version until $stateChangeCancel lands? |
Released just now with I've added a donations link on the homepage https://gratipay.com/rpocklin/ if you feel this feature has helped you out. |
@rpocklin, I have been using the 'workaround' in 1.4.2 since you released it. It works much of the time. However, in some instances (hard to put a percentage on it, but it happens often enough to be problematic, the added catch and associated update_tabs() are called, but the visually represented tab still moves. I know it feels hackish, but so far I have never had any similar 'failures' with this workaround: setTimeout(function() { Any idea what could be causing it, or if/when $stateChangeCancel will land? |
UI Router has been released with $stateChangeCancel so i'll be reviewing PRs this week and aim for a release end of next week. |
Changes have landed with 1.4.3 |
I have a scenario in which I am listening to the $stateChangeStart. In this case, I am verifying if the user has an unsaved changes and presenting a confirmation dialog to allow then to cancel (stay on the present tab and save the data) or continue (ignore their changes). All is working well with one important exception: event though I am calling event.preventDefault in response to the $stateChangeStart event, the tab is still be moved (i.e. the active tab class still changes) to the new tab the user clicked on. Is there a way to get ui-router-tabs to behave correctly in this situation (i.e. if the event is cancelled with preventDefault() then stay on present tab)? I have not seen anything in the docs or a quick review of the code, so would appreciate your assistance please.
The text was updated successfully, but these errors were encountered: