How to pass params to child window through ui-router - javascript

I have a requirement where I have a parent window with a button. Clicking on the button performs some logic, computes some values and opens a child window with those params. I'm trying to find a good way to do this. My current implementation is as follows.
Inside my ng-click method I have
let location = this.$state.href('moveout', { entityUuid: this.entityUuid, count: count, params: params, options: options);
let unDockedWindow = this.$window.open(location, '', 'scrollbars=no,fullscreen=yes,toolbar=no');
This successfully opens a child window with url that looks like the below
#/moveout?entityUuid=8eb6c75e-5a06-333c-a4cf-a97d90995722&count=something&params=something&options=something
I'm able to access the data in the destination like so
$state.params.entityUuid
My problem however is that, some of these attributes can be complex, like params and options. And I don't necessary want to have a url that has so many params and looks really ugly.
I'm trying to see if there is a way to open a child window with a number of params with ui-router without passing them as query string params.
I don't think I want to use ui-sref since some of the values that need to be passed need to be computed based on some logic. Hence doing it inside ng-click.
Any help, greatly appreciated.

Related

Vue 3 - Best way of using URL parameters for bookmark (like filtering)

I want to extend my application with a URL parameter functionality:
If a filter is activated, the URL needs to be updated
If someone goes directly to the URL you should get the same data as you filtered manually
I see different ways in this world:
The parameter story based on: domain.com/?status=pending&relation=1
Clearer/neat way: domain.com/filter/status:pending/relation:1
I'm more looking for the last example. How can I do this within Vue? I am currently working as an example within Router with props: route => ({ query: route.query }).
Can someone help me and maybe others on my way to realize this?
It dependes....maybe is better to create an api that refresh your table...
In this way you pass the parameter to the api that will get you the book array, and in this way you refresh your content...
In this way you will have a url like:
domain.net/page?f=1p=filterparamete
Or you can use vue dynamic routing
/page/:filter/:filter_value
But in this case you shold have a fixed url structure in case of multiple filter setting..
In any case the first way is the most easy and scalable way...
You can use the query-string lib to parse URL parameters and then just filter items by params
const queryString = require('query-string');
console.log(location.search); // '?status=pending'
const parsedParams = queryString.parse(location.search);
console.log(parsedParams) // { status: 'pending' };

Vue Router dynamic segment with params

I am trying to create a route that can handle both dynamic segments and accept router-props (params). Something like this:
{ path: '/peer:body?', name: 'peer', component: () => import('pages/peer.vue'), props: true }
And eventually push a route like this:
this.$router.push({ path: '/peer/' + row.body, name: 'peer', params: { row: row } })
Unluckily, I am only able to use dynamic segments using pathas route property or params using nameas route property, but never simultaneously.
First, as you already mentioned, when constructing "location descriptor object" for $router.push (or to prop of <router-link>), you can use path or name, not both at the same time (doesn't make sense to do so)
Second, you can pass params only when you use name (as described here - paragraph between first two code samples). To overcome this you can use query instead of params or build whole path including the params into the URL string.
And that brings me to the most important part of my answer. It seems as you are trying to pass a complex object as a route param (and into the target component props). While this is technically possible, it's not a good way of doing things. You have no place in your path definition where to put content of such parameter - it will work with push or clicking <router-link> where parameter is provided as an object, but when user accesses that URL directly (by copying and pasting URL for example), the page will be broken because prop parameter will be missing (as it cannot be extracted directly from the URL).
So my advise is to avoid that. Put your data into something like Vuex and instead of passing whole object by router, pass only some kind of identifier that can be included in the URL, extracted by Router and passed as a prop into target component. Then your target component should grab the Id and use it to query Vuex to get the data it needs...

Utilizing browser back/forward buttons in a vue.js app

I have an app that has a bunch of dropdown components that alter state. . The state of the dropdowns control a main datatable that has info based around the params. Cool.
I want to also alter the URL so users can share urls with their coworkers and simply have the datatable show up without choosing dropdown parameters.
Example: http://localhost:8080/?region=372&pc=341&pc=375 or http://localhost:8080/?region=372&pc=341&vendor=123456
Right now I've got this working by manually watching the dropdown parameters selected (via watch) and building a url and using this.$router.push to update browser history when things change. I have a feeling this isn't totally correct, but it's the only reliable way I've been able to make the url update consistently.
The main issue is that when I hit the browser's back/forward buttons, the components do not update their state based on the url. The application remains in it's current state if I hit back/forward. How do I properly go about this?
It looks like you're effectively trying to bind the state of your dropdown to your URL query. VueRouter, unfortunately, doesn't have a baked-in solution for this.
I'm not sure how your data is structured, so let's assume you have an object dropdownParams containing the relevant parameters:
dropdownParams: {
region: 372,
pc: 341,
vendor: 123456,
}
You need to set a watcher on dropdownParams to update the query in the $route when those are updated. Use $router.replace instead of $router.push so that the history doesn't change:
watch: {
dropdownParams(params) {
// format the data however you want this is an example with lodash
let query = _.pickBy(params, p => !_.isEmpty(p));
this.$router.replace({ query: query });
}
}
Then, in the mounted hook, you can set the dropdownParams object based on any relevant $route.query parameters, if they already exist:
mounted() {
let keys = _.keys(this.dropdownParams);
_.assign(this.dropdownParams, _.pick(this.$route.query, keys));
}
Now, when the user changes the dropdown parameters, those changes will be reflected in the URL. And, if the user loads the component with URL query parameters already present, the component will set those values to the dropdown.

How do I access URL parameters in Meteor helper functions?

For some of the pages in my application, I would like to enable a printable mode, wherein some elements of the page are hidden when the URL parameters include ?print=true. Currently I have attempted a workaround that involves sending the URL parameters as a data context thru iron-router.
this.route('permitsList', {
path: '/permits/',
path: '/',
waitOn: function(){
return Meteor.subscribe('openPermits');
},
data: function(){
return this.params;
}
});
Accompanied by a global handlebars helper which is used to show and hide elements appropriately.
In this case, when the URL contains ?print=true, it's trivial to show and hide the appropriate elements. However, this solution has two major issues. The first, is the fact that some of the pages for which I wish to implement this printable view already have a data context. Overwriting the data context is not viable, and embedding both data contexts into a larger object is rather disgusting. The second issue is that I wish for the printable view to apply not only inside the template itself, but also in the surrounding layout template in which the page is rendered, so that extraneous headers and so on are removed.
Is there any reasonable way to access URL parameters inside of a Spacebars helper without specifying the parameters in the data context through Iron Router?
To sum up as answer:
Query parameters can accessed even without meteor
if ( window.location.search.indexOf( '?print=true' ) > -1 ) { ... }
window.location returns the current URL, window.location.search only the query parameters as string.

How to redirect to different controller?

I have an application in ASP.MVC. The requirement is that I select a person from a list of people and click 'Info' and it should load the details of the person in that page. I have the Info controller and everything works fine if I go to the Info page from a different controller. In the page I am trying to make it work with JavaScript and it doesn't seem to take me to the desired page but to a different controller.
I have a ToDoList controller and in the .cshtml I have this code on click of the Info link.
function DoInfo#(i.ToString())() {
$("#sessionid").val("#Model.cSessionId[i]");
alert("hey");
$("#PageController").val(66);
$("#formID").submit();
}
I go to the ToDoList controller to do the redirection like this
if (viewModel.PageController == 66)
{
pass = new PassingData();
pass.personid = TSSessionService.ReadPersonId(viewModel.SessionId);
TempData["pass"] = pass;
return RedirectToAction("Index", "Info");
}
It never goes there and instead goes to a different controller. I cannot seem to find how they are linked and why is it not going back to controller where the Info link button is i.e. back to the ToDoList controller.
Let me know if it is not clear and I will try to explain again and I will give any other details.
I guess I'm confused as to why you are doing this as a combination of form and JavaScript. Are there other properties that you need to pass along that you are not posting above? Why do you need to use JavaScript to do this if you are just returning a new view?
You indicate in your post that when a person is selected from a list you need to go to a controller and display a view. This seems fairly straightforward, and I would like to suggest simplifying the problem.
Start with this: change your link to not use a form or JavaScript. Just make it a link. If it is text, you can use #Html.ActionLink() and even pass in the parameters you need.
If you're not displaying text, just use #Url.ActionLink() in your href property of the anchor you're wrapping your element with. Both of these allow you to leverage routing to ensure the correct path is being constructed.
If the controller that you are trying to get to has access to whatever TSSessionService is, then you don't need to pass through the TempData["pass"] you are trying to push through, so it makes it cleaner in that way as well.
If you do need to submit a more complicated value set, I would recommend coming up with a generic .click() event handler in jQuery that can respond to any of the clicks, bound by a common class name. You can use a data-val attribute in your link and read from $(this).attr('data-val') in your handler to store/fetch other important info. This allows you to more easily build up an object to POST to a controller.
Hope this helps some, but if I'm missing a critical point then please update the question above.

Categories