How to Create Ant Design group of Dynamic fields - javascript

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

Related

Interactive form for storing user information

I am learning to use HTML, CSS, JavaScript and JDBC. I want to integrate all the said together and arrive at a webpage that accepts user information that can be used to make a detailed profile of a family that can act as a repository for the family to access that information from anywhere by just logging into the website. I also want to do CURD operations to apply to all the data submitted. Need cascading dropdown menus that populate by themselves when one option is selected by user
I started off by making cascading dropdown menu that when province is selected the next dropdown selects only the corresponding cities in that province only. I was able to populate the first dropdown but could not connect it to subsequent dropdown
below is the JavaScript that I prepared for any number of cascading dropdowns but its not working and now I am unable to identify whats wrong with the code
function makeDropDown(data, filtersAsArray, targetElement) {
const filteredArray = filterArray(data, filtersAsArray);
//const filteredArray = data.filter((r) => r[0] === level1Filter);
//const uniqueOptions = new Set();
// using for each item of the array from the second place and put the valused in the uniqueoptions set
//filteredArray.forEach((r) => uniqueOptions.add(r[1]));
// deconstruting the set to form the array again
//const uniqueList = [...uniqueOptions];
const uniqueList = getUniqueValues(filteredArray, filtersAsArray.length);
populateDropDown(targetElement, uniqueList);
//selectLevel2.innerHTML = "";
//uniqueList.forEach((item) => {
//const option = document.createElement("option");
//option.textContent = item;
//selectLevel2.appendChild(option);
//});
}
function applyDropDown() {
const selectLevel1Value = document.getElementById("level1").value;
const selectLevel2 = document.getElementById("level2");
makeDropDown(myData, [selectLevel1Value], selectLevel2);
applyDropDown2();
}
function applyDropDown2() {
const selectLevel1Value = document.getElementById("level1").value;
const selectLevel2Value = document.getElementById("level2").value;
const selectLevel3 = document.getElementById("level3");
makeDropDown(myData, [selectLevel1Value, selectLevel2Value], selectLevel3);
}
function afterDocumnetLoads() {
populateFirstLevelDropDown();
applyDropDown();
}
function getUniqueValues(data, index) {
const uniqueOptions = new Set();
data.forEach((r) => uniqueOptions.add(r[index]));
return [...uniqueOptions];
}
function populateFirstLevelDropDown() {
const uniqueList = getUniqueValues(myData, 0);
const ele = document.getElementById("level1");
populateDropDown(ele, uniqueList);
}
function populateDropDown(ele, listAsArray) {
ele.innerHTML = "";
listAsArray.forEach((item) => {
const option = document.createElement("option");
option.textContent = item;
ele.appendChild(option);
});
}
function filterArray(data, filtersAsArray) {
return data.filter((r) => filtersAsArray.every((item, i) => item === r[i]));
}
document.getElementById("level1").addEventListener("change", applyDropDown);
document.getElementById("level2").addEventListener("change", applyDropDown2);
document.addEventListener("DOMContentLoaded", afterDocumnetLoads);

How to generate HTML text with a for loop?

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);

How to filter an array by two indvidual strings from an object?

I'm working on a project where I need to filter 13 items by two different select box values, and I'm getting stuck on persisting the filter.
I have two select boxes that I've selected like so:
let pickupLocation = document.querySelector("#pa_location"); //values are 'complete-set', 'neck', 'bridge'.
let pickupType = document.querySelector("#pa_type1"); // Values are 'soapbar', 'dogear', 'short'.
What's Working:
I'm initializing an object like so:
const activeFilters = {};
To populate the values like so:
//Persist the Complete Set / Single
pickupLocation.addEventListener("change", function () {
if (pickupLocation.value === "complete-set") {
activeFilters.location = "set";
} else {
activeFilters.location = "single";
}
});
pickupType.addEventListener("change", function () {
if (pickupType.value === "soapbar") {
activeFilters.type = "soapbar";
} else if (pickupType.value === "dogear") {
activeFilters.type = "dogear";
} else {
activeFilters.type = "short";
}
});
// Returns something like
// {location: single, type: dogear}
I'm trying to filter an array of input elements by their value. I have 13 inputs each with a value containing words like set, single, dogear, soapbar etc.
Where I'm stuck:
I have a filter function that I'm trying to filter the values of these inputs by two values of the activeFilters object:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
results = covers.filter((cover) => cover.value.indexOf(value) !== -1);
});
return results;
};
The problem is my function is returning only one of the two words. For instance, if the my activeFilters object is {location: set, type: dogear} the filtered results array contains only one of them. Where am I going wrong?
Edit:
This function returns all inputs that match one of the activeFilters, and I apologize if I wasn't clear above, but I'd like it to match ALL of the Active Filters. Is this possible with the function below?
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
results.push(...res);
});
console.log(results);
};
CODEPEN:
Codepen!
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
// push the value it find individually
// you were overriding the previous value with result = filter()
results.push(...res);
});
return results;
};
// according to Edited question
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
return covers.filter((cover) => filteredValues.every(value => cover.value.indexOf(value) !== -1));
};
I'm not sure if I understood clearly your question, so feel free to comment it.
First, I suggest you to filter your covers array and inside the filtering function iterate through your selected filters. This is because the filter function returns the array already filtered and so you don't need to assign it to a result variable or things like that. So based on that, try this:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
const filteredCovers = covers.filter((cover) => {
return cover.value.split("-").some((tag) => filteredValues.includes(tag))
});
console.log(filteredCovers)
};

How to get all data from a row as an object in cypress?

So, my web page has a table structure with multiple rows. I want to create a function which gets all the values from a row and creates an object with the header as the keys and the values. The kind of output I want:
header1 : value1
header2 : value2
This is what I have tried:
export const getRowObject = (rowIndex) => {
return cy.get(`[role='cell'][data-rowindex='${rowIndex}']`).then((values) => {
let rowObject;
values.map((i, elem) => {
if (!rowObject) {
rowObject = {};
}
rowObject[headers[i]] = Cypress.$(elem).text();
});
});
};
This is returning me an object with the index as key and the HTMLdivElements as the values.
Any help regarding this would be highly appreciated.
You are 90% there, just add an inner return
export const getRowObject = (rowIndex) => {
return cy.get(`[role='cell'][data-rowindex='${rowIndex}']`).then((values) => {
let rowObject = {};
values.map((i, elem) => {
rowObject[headers[i]] = Cypress.$(elem).text();
});
return rowObject;
});
};

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