How to generate HTML text with a for loop? - javascript

I have a list of expenses, I want to create a html code to iterate over all the expenses and show their name. I am not working with the DOM, I literally want to save the html code in a variable, so I can generate a pdf file with it.
This is what I tried:
lets say I have this array
const spents = [{expenseName: "Pizza"},{expenseName: "Home"}]
const testHtml = () => {
for(let i of spents) {
const title = `<h1>${i.expenseName}</h1>`
}
}
testHtml()
This is the result I want, something like:
htmlResult = "<h1>${i.expenseName}</h1> <h1>${i.expenseName}</h1>"
by the way, This is for a react native app.

I think this will work for you.
const spents = [{expenseName: "Pizza"},{expenseName: "Home"}]
const testHtml = () => {
let title = '';
for(let i of spents) {
title += `<h1>${i.expenseName}</h1>`
}
return title;
}
testHtml()

You could use Array.prototype.reduce().
const spents = [{
expenseName: "Pizza"
}, {
expenseName: "Home"
}];
const result = spents.reduce((prev, curr, index) => index === 0 ? curr.expenseName : `<h1>${prev}</h1> <h1>${curr.expenseName}</h1>`, '');
document.body.append(result);

Related

Is there a way to simplify this snippet?

const navTitle = document.querySelectorAll(".nav-sec");
const subTitle = document.querySelector(".subtitle");
const artTexts = document.querySelectorAll(".art-text");
const sectionTitles = document.querySelectorAll(".section_title");
const footerContent = document.querySelector(".footer_content");
const projectsTitle = document.querySelectorAll(".title-project");
const projectsDescription = document.querySelectorAll(".desc-project");
const aboutTitle = document.querySelectorAll(".about_title");
const contactContent = document.querySelector(".contact_content");
const aboutContent = document.querySelectorAll(".about_content");
btnLang.addEventListener("click", () => {
const attr = (btnEnglish.classList.contains("hiddden") ? btnPortuguese : btnEnglish).getAttribute("language");
navTitle.forEach((el, index) => (el.textContent = data[attr].navbar[index]));
sectionTitles.forEach((title, index) => (title.textContent = data[attr].navbar[index]));
projectsTitle.forEach((project_titles, index) => (project_titles.textContent = data[attr].project_titles[index]));
projectsDescription.forEach((project_description, index) => (project_description.textContent = data[attr].project_description[index]));
aboutTitle.forEach((about_title, index) => (about_title.textContent = data[attr].about_title[index]));
aboutContent.forEach((about_content, index) => (about_content.textContent = data[attr].about_content[index]));
contactContent.textContent = data[attr].contact_content;
subTitle.textContent = data[attr].subtitle;
footerContent.textContent = data[attr].footer_content;
});
I'm a benninger and I know that when you are repeating yourself too much, you can probably simplify things. But how can I approach something like this code? DRY ftw.
Assuming you have the same number of array elements in data as matching elements in the DOM, one approach is to use an array of selectors, each of which is tied to the associated property name on the data. Iterate over the selectors and language properties, then loop over each element matching the selector to assign the same index from the language property.
const selectorsByLangProp = [
['navbar', '.nav-sec'],
['navbar', '.section_title'],
['project_titles', '.title-project'],
['project_description', '.desc-project'],
['about_title', '.about_title'],
['about_content', '.about_content'],
];
btnLang.addEventListener("click", () => {
const attr = (btnEnglish.classList.contains("hiddden") ? btnPortuguese : btnEnglish).getAttribute("language");
const langData = data[attr];
for (const [langProp, selector] of selectorsByLangProp) {
document.querySelectorAll(selector).forEach((elm, i) => {
elm.textContent = langData[langProp][i];
});
}
contactContent.textContent = langData.contact_content;
subTitle.textContent = langData.subtitle;
footerContent.textContent = langData.footer_content;
});
For larger, complicated pages, a nicer approach to this sort of thing would be to construct the HTML directly from the data, instead of having separate selectors and properties. For example, with React, one might be able to do something similar to the following:
const Page = ({ langData }) => (<>
<div>{langData.subTitle}</div>
{
langData.sections.map((sectionData) => (
<section>
<div>{sectionData.project_title}</div>
<div>{sectionData.project_description}</div>
</section>
))
}
<footer>{langData.contact_content} {langData.footer_content}</footer>
</>);
(That isn't working code, but it's an example of what implementing this sort of thing could look like)

Don't make functions within a loop no-loop-func -React JS

I am trying to find index of array using lodash locationbar. but my react console showing some warnings. can be resolve?
let wishListData = wishList.result;
let j = 0; const jMax = wishListData.length;
for (; j < jMax; j++) {
var index = _.findIndex(products.result, function (product) {
return product.id === wishListData[j]['pid']
});
if (index !== -1) {
products.result[index]['isWishList'] = true;
}
}
Iterate over wishList.result with forEach instead of a for loop, and you'll avoid the warning:
wishListData.forEach(({ pid }) => {
const index = _.findIndex(products.result, ({ id }) => id === pid);
if (index !== -1) {
products.result[index].isWishList = true;
}
});
Note that this is a linter warning, not a Javascript error. Your code works, the linter just considers it to be confusing - better to use array methods instead of loops when possible.
Also, feel free to remove the _ library and just use built-in Javascript methods instead, if you want:
wishListData.forEach(({ pid }) => {
const product = products.result.find(({ id }) => id === pid);
if (product) {
product.isWishList = true;
}
});
Or, for an O(N) solution instead of an O(N^2) solution, figure out all pids first, then iterate over the products:
const pids = new Set(wishListData.map(({ pid }) => pid));
products.result.forEach((product) => {
if (pids.has(product.id)) {
product.isWishList = true;
}
});
You can try something like this as well:
Instead of mutating product in products.result[index]['isWishList'] = true;, you should create new object to minimize side-effect.
Also, instead of looping on wishListData, you can create a list of PIDs and just check index. If this list is created outside, you can create list of PIDs outside as well. That will reduce processing it every time
const wishListPID = wishList.result.map((x) => x.pid);
const result = products.result.map((product) => {
const isWishList = wishListPID.indexOf(product.id) !== -1;
return { ...product, isWishList }
});

How to Create Ant Design group of Dynamic fields

I'm using ant design dynamic form. How I suppose to create a group of dynamic forms
Code: https://codesandbox.io/s/vvl2yxqr5l
Scenario
User need to enter the team name and team members name dynamically.
Is it possible add the dynamic fields inside the dynamic field by ant design.
Yes, it is possible to create a nested dynamic form using ant design dynamic form component. I have also asked the same question How to create a questionnaire type form using Ant Design?. You need to add your own logic but here I am providing the basic structure:
To remove team name:
remove = k => {
const { form } = this.props;
const keys = form.getFieldValue("newkeys");
form.setFieldsValue({
newkeys: keys.filter(key => key !== k)
});
};
To add team name:
add = () => {
const { form } = this.props;
const keys = form.getFieldValue("newkeys");
const nextKeys = keys.concat(uuid);
uuid++;
form.setFieldsValue({
newkeys: nextKeys
});
};
To remove team member:
remove1 = (k, l) => {
const { form } = this.props;
const keys = form.getFieldValue("answerkey" + k);
let newkeys = [];
if (keys) {
newkeys = keys;
} else {
newkeys = [];
}
form.setFieldsValue({
["answerkey" + k]: newkeys.filter(key => key !== l)
});
};
To add team member:
add1 = index => {
const { form } = this.props;
const keys = form.getFieldValue("answerkey" + index);
let newkeys = [];
if (keys) {
newkeys = keys;
} else {
newkeys = [];
}
const nextKeys = newkeys.concat(uuid1);
uuid1++;
form.setFieldsValue({
["answerkey" + index]: nextKeys
});
};
I have created a working demo on codesandbox.io.
From above answer, I was trying to remove a team name with remove() function but getting some problem and i found this
Use map instead of loop, as map brings values at line 7 after render()
newkeys.map((i) => {
getFieldDecorator("answerkey" + i, { initialValue: [] });
})
Demo video

Could not get this point of javascript function

This is the code below, I am confused about this line.
What is this code doing? where does this title ( === title) comes from.
Plz, can anybody explain me about this?
var duplicateNote = notes.filter((note) => note.title === title);
var addNote = (title, body) => {
var notes = [];
var note = {
title,
body
}
try {
var notesstring = fs.readFileSync('notes-data.json');
notes = JSON.parse(notesstring);
} catch (e) {
}
console.log(Array.isArray(notes));
var duplicateNote = notes.filter((note) => note.title === title);
the filter function allow you to create a new array after filtering vaues of an old one
var duplicateNote = notes.filter((note) => note.title === title);
create an array duplicateNote containing entries of note where the entry's title is strictly equal to the title passed when calling the function.
It is equivalent to :
var duplicateNote = []
for (let note of notes) {
if (note.title === title) {
duplicateNote.push(note)
}
}

Draft.js. How to get all entities data from the ContentState

From official docs I know about 2 methods: get entity by its key and get last created entity. In my case, I also need a method to access all entities from current ContentState.
Is there any method that could perform this? If not, is there a one that can provide all entities keys?
const getEntities = (editorState, entityType = null) => {
const content = editorState.getCurrentContent();
const entities = [];
content.getBlocksAsArray().forEach((block) => {
let selectedEntity = null;
block.findEntityRanges(
(character) => {
if (character.getEntity() !== null) {
const entity = content.getEntity(character.getEntity());
if (!entityType || (entityType && entity.getType() === entityType)) {
selectedEntity = {
entityKey: character.getEntity(),
blockKey: block.getKey(),
entity: content.getEntity(character.getEntity()),
};
return true;
}
}
return false;
},
(start, end) => {
entities.push({...selectedEntity, start, end});
});
});
return entities;
};
How I get the all entities keys:
const contentState = editorState.getCurrentContent()
const entityKeys = Object.keys(convertToRaw(contentState).entityMap)
result:
[0, 1]
then you can call the getEntity(key) method to get the responding entity.
this is how convertToRaw(contentState) looks:
Bao, You will find it inside key called 'blocks'.
convertToRaw(contentState).blocks.map(el=>el.text)
It will give you an array of raw text.
Unfortunatelly your suggested way using convertToRaw doesnt work because it reindexes all keys to ["0", .., "n"], but the real keys differ when you act with the editor. New ones > n will be added and unused will be omitted.
const rawState = convertToRaw(contentState)
const { entityMap } = rawState;
This entityMap will have list of all entities. But this is an expensive conversion. Because, it will convert whole thing to raw. A better way is loop through blocks and check for entity.
You'll have to look at every character:
const { editorState } = this.state; // assumes you store `editorState` on `state`
const contentState = editorState.getCurrentContent();
let entities = [];
contentState.getBlockMap().forEach(block => { // could also use .map() instead
block.findEntityRanges(character => {
const charEntity = character.getEntity();
if (charEntity) { // could be `null`
const contentEntity = contentState.getEntity(charEntity);
entities.push(contentEntity);
}
});
});
Then you could access it via:
entities.forEach((entity, i) => {
if (entity.get('type') === 'ANNOTATION') {
const data = entity.get('data');
// do something
}
})

Categories

Resources