Let's say I have an object that contains the values:
const pathParams = { schoolId :'12', classroomId: 'j3'}
and I have a path: school/:schoolId/classroom/:classroomId
I would like to extract: 'schoolId' and 'classroomId' from the path so that I can later replace them with their corresponding values from the pathParams object. Rather than iterating from the pathParam object keys, I want to do the other way around, check what keys the path needs and then check their values in the object.
I currently have this:
function addPathParams(path, paramsMap) {
const pathParamsRegex = /(:[a-zA-Z]+)/g;
const params = path.match(pathParamsRegex); // eg. school/:schoolId/classroom/:classroomId -> [':schoolId', ':classroomId']
console.log('--params--', params)
let url = path;
params.forEach((param) => {
const paramKey = param.substring(1); // remove ':'
url = addPathParam(url, param, paramsMap[paramKey]);
});
return url;
}
function addPathParam(path, param, value) {
return path.replace(`${param}`, value);
}
Does this look robust enough to you? Is there any other case I should be considering?
Here's a couple of tests I did:
Result:
Related
This question already has an answer here:
using variable results (contents) to create new variables
(1 answer)
Closed 10 months ago.
I have a list
const StudentCode = {
Jack: 32658495,
Rose: 35621548,
Lita: 63259547,
Seth: 27956431,
Cathy: 75821456,
};
how can I use these peoples numbers if their names matches another variable result?
We have
var name = *selected server-side student names*
and by these * signs I mean it's a great list that name gives up but it only gives up one name out of that list at the time we call it.
If one of these students is selected by name variable, how can I use the number defined in front of that name in const StudentCode to generate a url?
Suppose you get Rose! Then the number for Rose is: 35621548 and the url for example will be https://www.35621548.com. What code can we use to generate this url for example in console?
console.log(url)
Use this:
if (StudentCode.hasOwnProperty(name){
const url = `https://www.${StudentCode[name]}.com`
}
This function will return you the url on the basis of the student name that is passed in this function.
function returnURL(studentName){
const StudentCode = {
Jack: 32658495,
Rose: 35621548,
Lita: 63259547,
Seth: 27956431,
Cathy: 75821456,
};
if (!!!StudentCode[studentName]) return "";
return "https://" + StudentCode[studentName] + ".com";
}
console.log(returnURL("Rose"));
Hope, this helps!!
const StudentCode = {
Jack: 32658495,
Rose: 35621548,
Lita: 63259547,
Seth: 27956431,
Cathy: 75821456,
};
let studentName = "Jack"
const url = `https://${StudentCode[studentName]}.com`
console.log(url)
export const studentUrlModule = (function() {
const studentCode = {
Jack: 32658495,
Rose: 35621548,
Lita: 63259547,
Seth: 27956431,
Cathy: 75821456,
};
const url = 'https://$code.com'
const generateUrl = function(code = '') {
if (!url) {
throw new Error('Url is not defined')
} else if (!code) {
throw new Error('Code is not defined')
};
return url.replace('$code', `${code}`);
}
function getCode(name = '') {
const code = studentCode[name];
if (!code) {
throw new Error(`There is no code with name(${name}).`);
}
return code;
}
function getUrl(name = '') {
if (!name) {
throw new Error('StudentName is undefined')
};
const code = getCode(name);
const studentUrl = generateUrl(code);
return studentUrl;
}
return {
generateUrl,
getCode,
getUrl,
};
}());
Maybe it helps. If the code was not founded then it throws an error. Please use try, catch error handlers to handle errors.
-- Update
I updated the code and as you can see it's a module and you need to import it everywhere you like to use this.
if you are not familiar with modules and how to use them inside the browser check documents.
Mozila documents
Super Simple Start to ESModules in the Browser
In our tool we create a url which quiet a few parameters with values. And I want Cypress to check the contents of this url.
The example url is:
http://someUrl.com/sap/?action=create&type=sw¬ifno=70432&repby=TRL&repres=ABC&geo=017&startloc=12345¬iftp=2021-06-15T08:06:42.379Z&scen=1.0&refno=1234567&awsrt=-&vrst=&sbst=&objtp=art&objtxt=&objfc=&tel=084123456&prio=4 Niet urgent&priost=&prioen=&wbi=&facts=&bgeb=AB-CD&bequi=
I have stored the url in 'href' variable but how i can now check all the attr and their values? I really don't have a clue.
I'd parse it into an object and then use .wrap(), .its(), and .should() commands:
const url = "http://someUrl.com/sap/?action=create&type=sw¬ifno=70432&repby=TRL&repres=ABC&geo=017&startloc=12345¬iftp=2021-06-15T08:06:42.379Z&scen=1.0&refno=1234567&awsrt=-&vrst=&sbst=&objtp=art&objtxt=&objfc=&tel=084123456&prio=4 Niet urgent&priost=&prioen=&wbi=&facts=&bgeb=AB-CD&bequi=";
const arr = url.split('/?')[1].split('&');
const paramObj = {};
arr.forEach(param => {
const [ key, value ] = param.split('=');
paramObj[key] = value;
});
cy
.wrap(paramObj)
.its('tel')
.should('eq', '084123456');
or if you want to assert more properties:
cy
.wrap(paramObj)
.then(obj => {
expect(obj.notifno).to.eq('70432');
expect(obj.tel).to.eq('084123456');
});
My colleague came with this solution, now the Cucumber line included:
Given('I expect the parameter {string} of the SAP-link on dossier {string} to equal {string}',(parameter:string, dossier:string, value:string) => {
cy.get('selector').each(ele => {
if(ele.text().trim().indexOf(dossier) == 0) {
cy.get('selector')
.parents('selector')
.find('selector').should('have.attr', 'href').then((sapUrl: JQuery<HTMLElement>) => {
cy.log(sapUrl.toString());
const queryParamString: string = sapUrl.toString().split('?')[1];
cy.log(queryParamString);
const queryParamArray: string[] = queryParamString.split('&');
var params: {} = {};
queryParamArray.forEach((keyValueString: string) => {
const currentParamArray: string[] = keyValueString.split('=');
params[currentParamArray[0]] = currentParamArray[1];
});
// Actual param check
expect(params[parameter]).to.equal(value);
});
}
});
});
I have a map of routes with react router path as keys, eg:
const routes = [
{
page: "mySettings",
label: "pages.mySettings",
path: "/professionels/mes-reglages.html",
exact: true
},
{
page: "viewUser",
label: "pages.viewUser",
path: "/users/:id/view.html",
exact: true
}
];
I want from a location retrieved with useHistory().location.pathname, to match all the path that match the key in react-router terms, eg:
(pathname) => get(routesMap, "/professionels/mes-reglages.html") => should match routesMap.get('/professionels/mes-reglages.html')
(pathname) => get(routesMap, "/users/11/view.html") => should match routesMap.get('/users/:id/view.html')
and all react-router paths so this should work too:
(pathname) => get(routesMap, "/users/11/settings/10/items/24/view.html") => should match routesMap.get('/users/:userId/settings/:settingId/items/:id/view.html')
I have started here, any idea how I can do that with a regexp?
https://codesandbox.io/s/youthful-wing-fjgm1
Based on your comments i adjusted the code a bit and wrote a rapper function for your lookup.
The following rules you have to watch out for when creating the urls:
The last id always gets replaced by {id}
All other ids get replaced by url part to id without plural and "Id" attached ("/users/111" -> "/users/{userId}")
This would be the function:
const getRouteFromPath = (map, url) => {
if (url.match(/\/\d+\//g).length > 1) {
let allowedUrlPart = getAllowedIdQualifier(map);
let urlParts = url.match(/(?<=\/)\w+(?=\/\d+\/)/g);
urlParts.forEach(val => {
if (!allowedUrlPart.includes(val)) {
urlParts = urlParts.slice(urlParts.indexOf(val), 1);
}
});
urlParts.forEach((val, key, arr) => {
if (key === arr.length - 1) {
let regex = new RegExp("(?<=/" + val + "/)\\d+", "g");
let replacement = ":id";
url = url.replace(regex, replacement);
} else {
let regex = new RegExp("(?<=/" + val + "/)\\d+", "g");
let replacement = ":" + val.slice(0, -1) + "Id";
url = url.replace(regex, replacement);
}
});
return map.get(url);
} else {
url = url.replace(/\/\d+\//g, "/:id/");
return map.get(url);
}
};
const getAllowedIdQualifier = map => {
let allowedQualifiers = [];
map.forEach(val => {
let allowed = val.path.match(/(?<=\/)\w+(?=\/:)/g);
allowed.forEach(e => {
if (!allowedQualifiers.includes(e)) {
allowedQualifiers.push(e);
}
});
});
return allowedQualifiers;
};
export default getRouteFromPath;
As parameter you pass in the url to match as first parameter and the map of routes as the second paramter and call the function getRoute() instead of the direct map.get() call you where using before.
Here is the example with the urls adjusted to follow the rules, since you need some rules to be able to apply RegEx.
EDIT:
I adjusted the script, so that it reads the map first and determines the allowed paths which accept a id and then check the possible ids from an actual url against it.
https://codesandbox.io/s/kind-moon-9oyj9?fontsize=14&hidenavigation=1&theme=dark
I'm using Vue, but I'm not using vue-router.
How can I get URI parameters?
I found one way to get URI by using root el property.
But is there any proper way to get the parameters as I want to send them to
backend and get a response from server and display it.
You can get the URL parameters by using window.location.search:
const queryString = window.location.search;
console.log(queryString);
// ?product=troussers&color=black&newuser&size=s
For parsing parameters of the query string, use URLSearchParams:
const urlParams = new URLSearchParams(queryString);
For more info, read this tutorial.
Since you are not using vue-router, I don't think you'll be able to access your params. So your only chance is to use the URL api as:
const URL = new URL(window.location.href);
const getParam = URL.searchParams.get('foo');
This will give you the value of foo in ?foo=bar
Alternatively, you can do something like this.
new Vue({
el: '#app',
data () {
return {
params: window.location.href.substr(window.location.href.indexOf('?'))
}
},
methods: {
getParam (p) {
let param = new URLSearchParams(this.params);
if(param.has(p)){
return param.get(p)
}else{
false
}
}
},
})
Now, just get the param using getParam('foo')
We don't use vue router for the moment either. We use the following script to parse args.
var args = {};
var argString = window.location.hash;
//everything after src belongs as part of the url, not to be parsed
var argsAndSrc = argString.split(/src=/);
args["src"] = argsAndSrc[1];
//everything before src is args for this page.
var argArray = argsAndSrc[0].split("?");
for (var i = 0; i < argArray.length; i++) {
var nameVal = argArray[i].split("=");
//strip the hash
if (i == 0) {
var name = nameVal[0];
nameVal[0] = name.slice(1);
}
args[nameVal[0]] = decodeURI(nameVal[1]);
}
Route properties are present in this.$route.
this.$router is the instance of router object which gives the configuration of the router.
You can get the current route query using this.$route.query
Is it possible to somehow append json objects onto a URLSearchParams object?
So instead of:
urlSearchParams.append('search', 'person');
it's:
urlSearchParams.append({search: "person"});
My answer courtesy of Darshak Gajjar's answer
Can use json objects via this way:
let test_this = [{"search": "person"}, { search: "another person"}];
var json = JSON.stringify(test_this);
urlSearchParams.append("myobj", json);
return this.http.post(this.post_url, urlSearchParams, options) //options being your own RequestOptions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Something like this might work urlSearchParams = Object.assign(urlSearchParams, {search: "person"});
EDIT: Alternate solution using vanilla javascript. Also, I thought URLSearchParams was just a normal js object, but in fact you have to use get, set and append to access properties.
var params = new URLSearchParams("a=apple&b=balloon");
var parametersToAdd = {c: "car", d: "duck"};
for(key in parametersToAdd)
params.append(key, parametersToAdd[key]);
console.log(params.get('c'));
console.log(params.get('d'));
EDIT bis:
.append() supports to re-use the same key/parameter name, while .set() would have overwritten a previous value.
May be using below code you can pass entire json object in URL Search param
var json = JSON.stringify(myObj);
this.http.get('url'+'?myobj='+encodeURIComponent(json))
There's no API for that. You just need to enumerate over the properties and append them manually, for example using the following function:
function appendParams(params: URLSearchParams, obj: any) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
params.append(key, obj[key])
}
}
}
appendParams(urlSearchParams, { search: 'person' });
Want to share my answer for Angular2 with the option of sending an Array
This is how I use this get function:
this.get('/api/database', {
'age': [1,2,3,4]
})
And the service is something like:
get(url, _params = {}) {
let params = this._processParams(_params);
return this.http.get(url, params).toPromise();
}
_processParams(obj: any) {
/* Convert this
{ age: [1,2,3] }
To:
param.append('age', 1);
param.append('age', 2);
param.append('age', 3);
*/
let params = new URLSearchParams();
for (let key in obj) {
for (let index in obj[key] ) {
params.append(key, obj[key][index]);
}
}
return {
search: params
};
}
Super simple answer/example:
// Create:
const params = new URLSearchParams({
a: 1,
b: 2
})
// OR
// const params = new URLSearchParams("a=1&b=2")
// Append
params.append('c', 'woohoo') // Note: if c param already exists in params, this will replace it (won't be adding new param if already exists, hence no duplications)
console.log(params.toString())
// Prints: 'a=1&b=2&c=woohoo'
Here is my approach. We have a simple requirement where the object is only a key value pair where the value might be a string or an array. We haven't found a use case for nested objects.
So let's say we want to convert this object into a query string or vice versa:
const input = {
ini: 'ini',
itu: 'itu',
ayo: ['desc', 'asc'],
}
Then we have two functions to parse & stringify:
function stringify(input) {
const params = new URLSearchParams();
for (const key in input) {
if (Array.isArray(input[key])) {
input[key].forEach(val => {
params.append(key + '[]', val)
})
} else {
params.append(key, input[key]);
}
}
return '?' + params.toString();
}
function parse(input) {
const payload = {};
const params = new URLSearchParams(input);
for(let [key, val] of params.entries()) {
if (key.endsWith('[]')) {
key = key.replace(/\[\]$/, '');
if (payload[key]) {
payload[key].push(val);
} else {
payload[key] = [val]
}
} else {
payload[key] = val;
}
}
return payload;
}
So the result should be "?ini=ini&itu=itu&ayo%5B%5D=desc&ayo%5B%5D=asc". This is similar to the array format that is found in this example.
Please note that this might not be battle tested, but for us we don't really have complicated object structure.
const url = new URL('/', location.origin);
console.log(url.href); // https://stackoverflow.com/
Object.entries({this:4,that:1}).forEach((item)=>{
// note .set replaces while .append will duplicate params
url.searchParams.append(...item);
});
console.log(url.href); // https://stackoverflow.com/?this=4&that=1