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!
Related
I have a search page, where the user can perform a search and see a result.
Initially, my issue was to update the router URL without navigating, but I solved that by using "Location".
My ngOnInit - my search page can be navigated to by another page, so I listen for queryParams to perform the search if any happens:
ngOnInit() {
this.queryParamsSubscription = this.activatedRoute.queryParams.subscribe(queryParams => {
this.searchText = queryParams[TD_QUERY_PARAMS.text];
if (this.searchText) {
this.search();
}
});
}
my search method:
search() {
const queryParams: Params = { text: this.searchText };
const desiredUrl = this.router.createUrlTree([], {
queryParams: queryParams,
relativeTo: this.activatedRoute,
skipLocationChange: true
});
this.location.replaceState(desiredUrl.toString());
}
This implementation makes sure that I update the URL when the user searches within the search page, which was the first part of my solution.
However, I also want to add any search to the browser history, ie:
I start by launching my application on 'localhost:4200/landing'.
On this page, I have a search bar, that when triggered will navigate to my search page.
From the landing page, I search for '1'. The router then navigates to: 'localhost:4200/search?text=1'
Then on the search page, I search for '2'. the search is performed, and the URL is updated to: 'localhost:4200/search?text=2'
Finally I search for '3': ''localhost:4200/search?text=3'.
When I then press the browsers 'Back' button, I would expect to be navigated to ''localhost:4200/search?text=2'.
However, none of the searches I made within the page has been added to history, so I will be navigated to whatever page I was accessing before the search page. In my case, 'localhost:4200/landing'.
How can I add each of these searches to the browsers history?
I believe that one of these is what yo need:
this.router.navigate(['/yourRouteGoesHere'], { replaceUrl: true });
The other options that you have is to use: SkipLocationChange this.router.navigateByUrl(['yourFullPath'], { skipLocationChange: true });
use this.router.replaceUrl('path').
That way you can navigate, without adding this route to history.
This was a case of way overthinking the issue I was facing.
By just using router.navigate(['/search'], { queryParams: queryPrams })
I got the result I desired. The URL was changed, a point was added to browser history.
What I failed to realize, was that router.navigate, will not reload the entire page, when only the queryParams are changed.
Hope this helps anyone struggling with the same issue.
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.
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.
In my ember app, when the user clicks the Back button of browser,I need to stop the transition (whereever it might take me as per Ember history) and reload the same url with same model. Have tried the below code, but doesnt seem to work:
search-route.js
var route = Ember.route.extend({
actions:{
willTransition: function(transition){
if(this.controller.get('order') === 1){
transition.abort();
this.transitionTo('search',model)
}
}
}
})
This doesnt seem to work and gives error about query params. So, i looked for what is there in transition object. Saw that as soon as I enter this code, the object transition contains prop queryParams but with the old values, not the current URL one. But there is another prop - transition.intent.preTransitionState.fullQueryParams which contains the current URL query params. Would that be used here somehow.
I looked for solutions and someone also suggested to put in this.refresh(), but also didn't work.
I'm trying on my own ember app and doing a transition.abort() followed with a this.refresh() works.
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