Any ember-way ideas to make a manual transition to a wildcard route with a dynamic segment at the end */:category_name, so I can manually build a "breadcrumbish url version" example, suppose a user enters to /banana I need to transition the user to /Groceries/Healthy/Fruit/Banana.... groceries, healthy, fruit might be entered as well so /Fruit would be transitioned to /Groceries/Healthy/Fruit... I was able to make it work using window.history.replaceState on the model hook of the route but strange enough it only works if it's being refreshed or type in by user, not while transitioning in template, thanks in advance guys
Route as is
this.route('products', function(){
this.route('wildcard_handler', {path: '*/:category_name'});
this.route('handler', {path: '/:category_name'})
});
Recap of cases:
Case 1:
User enters /products/banana
-Redirect to /products/groceries/healthy/fruit/banana
User enters /products/fruit
-Redirect to /products/groceries/healthy/fruit
Case 2:
User enters /products/groceries
-All good, it's correct.
Case 3
User enters /products/groceries/snacks
-doesn't exists so, 404 redirects.
All of this trouble is only for making a better UX for a new ecommerce I'm building, the normal suggested way is to just use one dynamic segment
Like
this.route('products', function(){
this.route('handler', {path: '/:category_name'})
});
It's fair, but it's way nicer to build the breadcrumbish url
Again, thanks in advance
Case 1:
If you want to redirect the user to another route before resolving the model, you can use beforeModel() hook. You can also use redirect() hook to redirect the user to another route. For example (when user visits /products/fruit, you can redirect them to products/groceries/healthy/fruit in redirect hook),
redirect(model, transition) {
this._super(...arguments);
this.transitionTo('products.groceries.healthy.fruit');
}
Refer this link to know about the predefined hooks in routes.
Case 3:
Refer this link to know about wildcarding routes in your application.
Related
I'm building a search bar for my app with vue-bootstrap-typeahead autocomplete lib, if your not familiar with it, when you click a suggested result it triggers the #hit event, passing the result data to the method.
<vue-bootstrap-typeahead
...
#hit="goToResult"
...
/>
Then I have the goToResult method
methods: {
goToResult(result) {
this.$router.push({name: 'market', params: {marketId: result.id}});
},
...
}
When I do search from a non-market route it works fine, redirecting the user to the desired /market/:marketId route, but when it's done from a "market" route it just changes the URL but doesn't redirects to the new market, it even triggers the "duplicated route" error if I click the same result twice, but still not redirecting.
Any suggestion?
Thanks
Check out the note at the bottom of the router.push section: https://router.vuejs.org/guide/essentials/navigation.html
Note: If the destination is the same as the current route and only params are changing (e.g. going from one profile to another /users/1 -> /users/2), you will have to use beforeRouteUpdate to react to changes (e.g. fetching the user information).
...and here is how to use beforeRouteUpdate:
https://router.vuejs.org/guide/essentials/dynamic-matching.html#reacting-to-params-changes
Hope this helps!
Okay, I have two use cases for my question here:
I'm working on an application which has a /en/register route. It all works good when I'm at the root and I click a button that does this.router.navigate([this.routeParams.lang, 'register']); and it's all good, this opens up a modal in the constructor (or ngOnInit, anyways) with ($('#modalRegister') as any).modal('show');.
It all works good, but if I close the modal, the route is still /en/register/ (yeah I can make it go to /en but see the use case #2 before you suggest this), so when I click the button, it doesn't do anything. Neither the constructor or ngOnInit are being called, not even route.params.subscribe() or route.url.subscribe() (which I think they should...).
In the same application, I have a button that does a search and centers some markers in a map (in /en/search/blah). That's all good if I'm in the index page or if I change the search query. However, if the user drags the map somewhere else and wants to have the same markers centered again, I also do this.router.navigate(['search', this.searchQuery]); and if it ends up being the same route (click the search button twice, for instance) it doesn't do anything.
While I agree it's good so the components don't get recreated if the URL hasn't changed, this is a bad design because in UI-router you could do the same thing and it'd work (as far as I can remember).
So, in Angular 4, how do I run the same code in the constructor/ngOnInit of the route's component when the same URL is being told to be navigated to? or how do I detect if the URL is the same and act accordingly? (although I still think it's bad design, but anyway...).
Any advice is greatly appreciated. Thanks!
When I needed to "reload" the current component's constructor and ngOnInit functions,
the only solution I found was kind of a workaround:
I used the fact that "this.router.navigate" returns a promise.
So I navigated somewhere else, and returned. It's a bit ugly but it works and the UI is not affected:
this.router.navigate(..[somewhere else]..)
.then(()=>{this.router.navigate(..back..)})
Hope it helps.
For case 1,
Why do you navigate to a new route just to open a modal. Just do it being at the same route with a function call. If you want to move to a new route then you can again call this.router.navigate("/") in modal close event.
For case 2,
Hope this will work.
currentSearchQuery: string;
ngOnInit() {
this.route.paramMap
.switchMap((params: ParamMap) => {
this.currentSearchQuery = params.get('searchQuery');
updateMarkers();
});
}
i use this workaround
this.router.navigate(['path']).then(()=> {window.location.reload();});
Just add dummy parameter at the end of the route /en/register/jk2h4-42hj-234n2-234dfg or query parameter like /en/register?val=jk2h4-42hj-234n2-234dfg
change the parameter value when calling the same route. So browser knows that URL change and Angualr component start to work from full life cycle.
please see this functioning JSBin: http://jsbin.com/acUm/20
Here is the behavior I am working on. If I type 'Monroe' to filter the list down and then hit the browser back button, I expect Ember to process the route and fire the request for all patients. Instead it appears to do nothing. This is especially confounding since the back button seems to work in other areas.
Perhaps I have set up this transition improperly? Or is this an Ember.js bug?
When you transition to a route, it's a good idea to use the childest route in the hierarchy.
In your case you have this:
this.resource('patients', { path: '/' }, function() {
// this is created for you
// this.route('index');
this.route('filtered', { path: '/filtered/:last_name' });
});
By default is created a route index for that resource, so you have the patients.index.
But your transition goes to patients and it isn't the childest.
So to correct this, I have changed your sample to use PatientsIndex[Controller,Router etc], instead of Patients[Controller,Router etc].
Working demo http://jsbin.com/acUm/24/edit
I've been doing some research and it appears that the popstate event fires any time that the history is changed, but there doesn't seem to be a built in way to determine whether the user clicked the back button or the forward button in the browser.
My use case is that when going back in the history or forward in the history I have directional animations that occur when transitioning routes in an ajax application. I need to determine if the user is going backwards or forwards so the animations make sense. It's a shame that the popstate event doesn't support the direction of the event.
I'll also mention that my application is an AngularJS application in case there is a angular specific answer, although a more general purpose javascript solution would be optimal.
I'm not sure which understanding is correct, but my understanding of HTML5 pushstate is different.
Push-state support simply allows you to capture changes in the browser's URL that would otherwise be sent as a request to a server (yours or someone else's). The purpose isn't to give you "forward" and "back" events, but more like general "location change" events. Then it's your app's job to check the URL and figure out where the user is trying to go.
Think about it this way: What if the user clicked a link in your app that you wanted to handle with javascript? You would have some event handlers setup which would capture the click and manipulate your app in some way. So clicking "back" or "forward" is like clicking a link, but all you get is the URL that the user is trying to view -- there's no link to bind events to.
So how do you know what the user is trying to do? You could manage state using global variables or any other way you can come up with. If you wanted to reduce code duplication, you could handle all of your app routing using URLs. So your click handler wouldn't bind to a particular link (or set of links), instead you could capture changes in the browser's URL and then determine how to handle the new URL.
BackboneJS does this using a Router object where specific paths are tied to specific router functions, which set the state of the app a particular way, for example:
MyAppRouter = Backbone.Router.extend({
routes: {
'home': 'setupHomeScreen',
'recipes': 'setupRecipesList',
'recipes/:id': 'setupRecipeScreen'
},
setupHomeScreen: function() {
// ...
},
setupRecipesList: function() {
// ...
},
setupRecipeScreen: function(id) {
// ...
},
// ...
});
Please excuse the Backbone code on an Angular question. I'm still learning The Angular Way, and coming from a Backbone background that formed my understanding of pushstate.
To answer your question
If your views form some kind of hierarchy or order, you could store that in a global variable. Maybe you decide to come up with IDs for each view, and then every time the browser state changes, you push those IDs onto an array.
var viewHistory = [];
// ... they visited the recipe list. push it into the history
viewHistory.push('recipeList');
// ... they visited a particular recipe. push it into the history
viewHistory.push('recipe:13');
// ... they clicked the "back" button. we know from the URL that they want
// the recipeList, but we don't know if they're trying to go forward or back.
var nextView = 'recipeList';
if (viewHistory.indexOf(nextView) > 0) {
// *** Back Button Clicked ***
// this logic assumes that there is never a recipeList nested
// under another recipeList in the view hierarchy
animateBack(nextView);
// don't forget to remove 'recipeList' from the history
viewHistory.splice(viewHistory.indexOf(nextView), viewHistory.length);
} else {
// *** They arrived some other way ***
animateForward(nextView);
}
I'm trying to create a little wizard with backbonejs in which the answers to certain questions determine the path being taken through the wizard. Is there a way in backbonejs to assess the current state of the model and navigate to the next page accordingly? Or is there another way of accomplishing this best in a backbonejs kind of way?
I think the best way is to treat each answer as a different route. That way when the user selects an answer, the route is change and you can load/change views accordingly in your router. Be sure to make use of variables in routes like
routes: {
":question/:answer": "checkAnswer"
}
Where question and answer are variables
Hope this helps
You can have your router subscribe to the model's "change" or "change:[attribute]" event, then change the route and page accordingly
OR whenever you want to go to a new page call the router's navigate function
router.navigate("question1/option1", {trigger: true});
This will change the url and also trigger the route you set up for "question1/option1"
So if your router is:
router = Backbone.Router.extend({
routes: {
"question1/option1": "answer1"
},
answer1: function() {
//change the page / or take whatever other action you want.
}
answer1 function will be called to setup your next page.