Ignore undefined value when concatenating words split by comma? - javascript

I would like ignore the initial value undefined of string variable, I'm trying concatenate words separate by comma but the first concatenation is an undefined. I can not use array of string.
Can it ignore undefined value?
MyComponent.ts
addTag(tag: any){
this.tags = `${this.asunto.etiquetas}, ${tag}`;
(<HTMLInputElement>document.getElementById("tags")).value = '';
}
View of my angular component

You should put the etiquetas when available, otherwise an empty string. Since you can write normal Javascript inside that template literal:
addTag(tag: any){
this.tags = `${this.asunto.etiquetas ? `${this.asunto.etiquetas}, ` : ""} ${tag}`;
(<HTMLInputElement>document.getElementById("tags")).value = '';
}
A better version would be to just use a variable
addTag(tag: any){
const etiqueta = this.asunto.etiquetas ? `${this.asunto.etiquetas}, `} : "";
this.tags = `${etiqueta}${tag}`;
(<HTMLInputElement>document.getElementById("tags")).value = '';
}

Related

Accessing dynamic properties of an Object in React

I’m checking whether there is a placeholder present in the “all” string within alertDetails object so my question is I need to access email,sms,fax property that appears dynamically based on user’s input (the code is a part of an alert box in which an user can choose to send alert via different delivery methods) so I saved all the possible delivery methods in an array and tried like below;
Const delmethod=[“email”,”sms”,”fax”]
for(let i=0;i<delmethod.length;i++)
{
Console.log(alertDetails &&
alertDetails.alertMessage &&
alertDetails.alertMessage[${lang}] &&
alertDetails.alertMessage[${lang}].all
? alertDetails.alertMessage[${lang}][‘${delmethod(i)}’].includes('placeholder')
: false;
}
P.S:the property “all” is fixed it’s just the email fax will be changing based on user’s input, to sum it up I want to return true if “placeholder” exists in any of the strings(all,email,fax,sms) the method I tried just prints the del method array, I’d appreciate any help thanks!
There are multiple issues with your code. You cannot just use ${lang}. You must surround your string with backticks (`) if you want to use template literals.
To access properties of an object you need a a key i.e. a string which you already have so in this case template literals are not required at all.
When you access an array by index you need to use [] not () so use delmethod[i] instead of delmethod(i). Additionally make sure an property exists on an JavaScript object.
const delmethod = ["email", "sms", "fax"];
const alertDetails = {
alertMessage: {
en: {
all: "emailsfsdfsdfsd",
fax: "placeholder",
sms: "sdkjföskjfsödkj"
},
},
};
const lang = "en";
for (let i = 0; i < delmethod.length; i++) {
if (
alertDetails &&
alertDetails.alertMessage &&
// use backticks ` when trying to use template literals
alertDetails.alertMessage[`${lang}`] &&
// there is actually no need for template literals here
alertDetails.alertMessage[lang].all &&
// you need to make sure "sms" or "fax" or "email" key actually exist on the object
alertDetails.alertMessage[lang][delmethod[i]] &&
alertDetails.alertMessage[lang][delmethod[i]].includes("placeholder")
) {
console.log(
`alertDetails.alertMessage[${lang}][${delmethod[i]}] does have a placeholder`
);
console.log(true);
} else {
console.log(
`alertDetails.alertMessage[${lang}] does NOT have property ${delmethod[i]} or does NOT have a placeholder`
);
console.log(false);
}
}

Split out props.location.search value

I'm trying to split out the values from props.location.search in React/Redux. I've successfully obtained the mixOne split however I can't seem to return the value of quantity. Here's my code:
const mixOne = props.location.search
? String(props.location.search.split("mixOne=")[1])
: "None";
const quantity = props.location.search
? Number(props.location.search.split("=")[1])
: 1;
And here's the URL that gets generated:
const addToCartHandler = () => {
props.history.push(
`/Cart/${productId}?quantity=${quantity}?mixOne=${mixOne}`
);
};
As you can see quantity returns null, when I need the value selected
props.location.search.split("=") on "?quantity=1?mixOne=Grape" would return [ '?quantity', '1?mixOne', 'Grape' ] since the next = is not until after mixOne.
There's a few different fixes here.
Your query string is invalid– a ? denotes the start of the query string. Separate parameters should be split up using & ampersand characters. It should look like this: ?quantity=1&mixOne=Grape
If you follow the standard here, you can then split it two ways: by = and then by & to get the different parameters. However, there is an easier way.
Using the new-ish URLSearchParams API, you can parse your parameters in a predictable way:
// Use the constructor with your `props.location.search`
const queryParams = new URLSearchParams(props.location.search);
// Use the getters to grab a specific value
const quantity = queryParams.get("quantity");
// Ensure it's a number for safety
const quantityNum = Number(quantity);
// ... the rest of your code here
The query is wrong. You're using double question marks. The second ? should be replaced with &.
?quantity=1&mixOne=Grape

JavaScript: Finding successive matches with .exec()

I have an object with a myriad of properties, such as color and brand, that describes a product. I'm looking for a way to dynamically generate product descriptions in paragraph form (because API doesn't provide one), and I came up with a way to do so by writing "templates" that have "props" surrounded in brackets {{}}. I wrote a function to "parse" the template by injecting the object properties in the string by replacing the "props" with the value of the key.
For example:
Object: {color: 'white'}
Template: "The bowl is {{color}}."
Result: "The bowl is white."
For some reason, my parse function isn't working. {{general_description}} isn't parsed.
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
I followed the example provided in the MDN docs under Examples > Finding successive matches. It says that I need to first store the regular expression in a variable (e.g., templatePropRe), for the expression cannot be in the while loop condition or it will loop indefinitely. However, if I do that, my problem is resolved. See here...nothing broke.
I rewrote the function using String.prototype.match, and it works as expected, but I don't have access to the capture so I need to first strip off the brackets using stripBrackets. See the working example using match here.
What I want to know is why doesn't my parse() function that utilizes RegExp.prototype.exec work properly?
Remove the /g flag from your regex. According to the documentation, when this flag is present, it updates the regex object's lastIndex property which indicates from where next call to exec() will start to search a match.
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
This happened because you modify and check the same string in your code.
Whereas regExp saves index of matched substring after each execution you change length of the string and regEx with next execution starts from other point than you expect.
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
var resultStr = template;
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
resultStr = resultStr.replace(match, obj[key]);
}
return resultStr;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
Instead of performing the 2-step replacement (finding a match and then replacing the first occurrence with the required value) (that is prone with issues like the one you encountered when a new string is passed to the same RegExp with old, already invalid, index), you may use a callback method as a replacement argument inside a String#replace method. That way, the resulting string will be constructed on the fly upon each match making the code execute faster.
See an example fix below:
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const parse = (template) => {
return template.replace(/{{(\w*)}}/g, ($0, $1) => obj[$1] ? obj[$1] : $0 );
// ES5 way:
// return template.replace(/{{(\w*)}}/g, function($0, $1) {
// return obj[$1] ? obj[$1] : $0;
// });
}
console.log(parse('{{keep}} This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
Note that here, after finding a match, the ($0, $1) => obj[$1] ? obj[$1] : $0 code does the following: the whole match is assigned to $0 variable and the Group 1 value is assigned to $1; then, if there is a key with the name $1 in obj, the value will be put instead of the match into the right place in the resulting string. Else, the whole match is put back (replace with '' if you want to remove a {{...}} with a non-existent key name).

Create address from multiple strings and separate them by comma

let's imagine, I've got 5 strings and any of it can be filled in or just stay empty (it's based on user input)
I wonder how to separate them nice with comma. I feel like this problem have to be trivial but only idea I found out that will work and is not totally stupid is:
// Create a function which return me string of arrays
public getAddress(): string[] {
let result = [];
if (this.application.applicant.city) {
result.push(this.application.applicant.city);
}
if (this.application.applicant.postalCode) {
result.push(this.application.applicant.postalCode);
}
if (this.application.applicant.state && this.application.applicant.state.name) {
result.push(this.application.applicant.state.name);
}
return result
}
// Then somewhere in ngOnInit() just call this method:
this.address = this.getAddress();
And inside of my tempalte:
<span *ngFor="let item of address; let isLast=last">
{{item}}{{isLast ? '' : ', '}}
</span>
or clasic JS way:
<span> {{address.join(", ")}} </span>
And I still feel like this is overcomplicated. Am I missing some easy solution?
Thanks for any advise
There is a typescript function to split a string. It also remove the ,
this.addres = this.address.split(', '); // this is now an array instead of a string.
EDIT
I create a string and but the newValue in it the newValue can be anything.
let string = '';
if() {
string = `${string}, ${newValue}`;
}
here is a sample solution than yours ,you create the address's string in your method and show it directly in your html template (i think it's more simpler than iterating on the array.. )
in your .ts :
address : string ;
// Create a function which return me string of arrays
public getAddress(): string {
let result = "";
if (this.application.applicant.city) {
result.push(this.application.applicant.city+",");
}
if (this.application.applicant.postalCode) {
result.push(this.application.applicant.postalCode+",");
}
if (this.application.applicant.state && this.application.applicant.state.name) {
result.push(this.application.applicant.state.name+",");
}
if (result.length !== 0 )
result.substring(0, result.length-1);
return result
}
// Then somewhere in ngOnInit() just call this method:
this.address = this.getAddress();
in your HTML template :
<span>{{address}}</span>
Hope it helps :)

How to write Variable inside of Variable in Template String literal?

log(`${chalk.magenta('🤖 LAUNCH_COMMAND')} ${chalk.green('npm run: ')} ${chalk.red('${LAUNCH_COMMAND}')}` );
Here is the problem part: ${chalk.red('${LAUNCH_COMMAND}')}
LAUNCH_COMMAND is either 'production' or 'development'. However it's inside of another ${}.
Demo
Just use the Variable name for nested Variable in Template String literal
`${chalk.red(LAUNCH_COMMAND)}` // for nested sting literal just use the variable name
const LAUNCH_COMMAND = 'hi';
console.log(`${chalk.magenta('🤖 LAUNCH_COMMAND')} ${chalk.green('npm run: ')} ${chalk.red(LAUNCH_COMMAND)}` );
You don't wrap variables within string literals with quotes.
log(`${chalk.magenta(🤖 LAUNCH_COMMAND)} ${chalk.green(npm run: )} ${chalk.red(LAUNCH_COMMAND})` );
^ Should hypothetically work though I'm not clear on the context behind why you're writing a string like this. I'm assuming it's some kind of dynamic output.
var b = "Cats"
var c = "Dogs"
function concat(one, two) {
return `${one} and ${two}`;
}
function compare(one, two) {
var ans = one == two ? 'Are the same' : 'Are not the same';
return ans;
}
console.log(`${concat(b, c)} - ${compare(b, c)}`);

Categories