Whenever I select a person from the list it grabs the id of a name and stores it an array with map.
I then have a string literal which gets populated with the ID.
const id = value.map(person => person.value)
console.log('from',id)
current output:
[u29219]
withe the results looking like this:
const results = await verifiedGet(`get_user/?$u29219?admin_form=True`, user.user)
and then if I add another person the array would look like this
[u29219, u302932]
results:
const results = await verifiedGet(`get_user/hello?$u29219,u302932?admin_form=True`, user.user)
When a user is added to the array I want to be able to iterate through the results with the ID only populating once if a user is selected twice
const results = await verifiedGet(`get_user/?$u29219?admin_form=True`, user.user)
const results = await verifiedGet(`get_user/?$u302932?admin_form=True`, user.user)
is this possible to do so?
I created a sandbox for a better understanding
https://codesandbox.io/s/modest-star-fegy7
I would take your unique id array and use Array.Join() to combine them with commas.
// Map the ids, and filter unique
const uniqueIds = value
.map((person) => person.value)
.filter((value, index, self) => self.indexOf(value) === index);
// Join the Ids and separate them with commas
const commaSeparatedIds = uniqueIds.join[','];
// Don't forget to make them safe for a URL
// You may be able to skip this if you are certain
// your string is safe
const uriSafeIds = encodeURIComponent(commaSeparatedIds);
// Finally, interpolate into your string literal template
// I wasn't sure if the extra $ in your code was intended
// so I left it in.
const url = `get_user/hello?$${uriSafeIds}?admin_form=True`;
const results = await verifiedGet(url, user.user);
In the line const id = user.map((person) => person);, we are looping through the 'user' array and for each iteration, we are just returning the element in that iteration. The 'map' function will return an Array of what will be returned in each iteration. So, basically, we are re-creating the user array in id.
const user = ["u29219", "u302932"];
// 'user' array is re-created here
const id = user.map((person) => person);
console.log("from", id);
const results = `get_user/?${id}admin_form=True`;
If your intention was to form the results string with each element in the array, this would be a way to do it using forEach:
user.forEach((person) => {
const results = `get_user/?${person}$admin_form=True`;
// remaining logic
});
Code-Sandbox
Can make the array unique, then concat or join to get the expected output.
const user = ["u29219", "u302932", "u302932"];
const uniqueItems = [...new Set(user)];
console.log("current uniqueItems", uniqueItems);
let results = "";
uniqueItems.forEach((person) => {
results = results.concat(`get_user/?${person}$admin_form=True `);
});
console.log("current output", results);
Related
so at the moment I have a collection that looks like: https://i.stack.imgur.com/lxYoA.png . So in this collection it has a list which consists of nested lists. But I basically want to do a for loop that will add all of this to just one list, but what I'm doing below is just adding an empty list to firebase?
In firebase, I've added individual lists to another list as the documents consist of lists which I have done below and it creates the screenshot that I have above.
const snapshot = await fire.firestore()
.collection("groupsCategory")
.doc(groupID)
.collection('events')
.doc(eventID)
.collection("memberPicks").get()
const data = snapshot.docs.map(doc => doc.data())
snapshot.docs.map(doc => doc.data())
const db = fire.firestore();
const likesList = [];
snapshot.docs.forEach((doc) => {
likesList.push(doc.data())
})
As you can see here, I'm trying to get each item in the list and have it in one list and not a list of nested lists. Where am I going wrong?
const arr1 = likesList.flat();
const newArr = [];
for (let i = 0; i < arr1; i++) {
newArr.push(arr1[i])
}
db.collection("eventLikes")
.doc(eventID)
.set({
ActivityLikes: newArr
})
}
As far as I understand your question, you want to set a document which doesn't have a nested list of userLikes. To be able to achieve that you should iterate the data in which you're fetching the objects of userLikes and pushing it into an array. See code below:
var userLikes = [];
const snapshot = await db
.collection("groupsCategory")
.doc(groupID)
.collection('events')
.doc(eventID)
.collection("memberPicks").get()
snapshot.docs.forEach((doc) => {
// Gets the List of `ActivityLikes`
const activityLikes = doc.data().ActivityLikes;
// Iterate the List of `ActivityLikes`
activityLikes.forEach((activityLike) => {
// Push the data object of `userLikes` to the initiated array: `userLikes`
userLikes.push(activityLike.userLikes[0]);
})
})
// This sets the data as follows:
// Map (ActivityLikes) > Array (userLikes) > Map (userLikes Object)
db.collection("eventLikes")
.doc('eventID')
.set({
ActivityLikes: {userLikes}
})
Added some comments on the code above to better understand.
Here's the screenshot of the result:
Take a look at these documentation to better understand working with objects and arrays:
Working with objects
Arrays
I'm working with the outputs of an Intranet I don't control.
I have this string:
let template = 'LAWYER=|FIRM=|SUIT_DESCRIPTION=|DEF_COMMENT=|PLF_COMMENT=|';
It goes on longer, but that's the pattern.
Now there's another similar string, but with data assigned, as in this example:
let current= 'FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|PLF_COMMENT=some freeform text|LAWYER=Bob Smith';
Now, notice that not every element in template is necessarily represented in current, and the order may be different (if the latter fact is a big deal, I can ensure the order is the same).
What I'm trying to do, is take every element that is in current, and populate the matching element in template, if it exists. (or, alternatively and potentially preferred, insert every non-matching element in template into current, but ideally in the same order as template).
Using the date above, the result I'm looking for is:
result = 'LAWYER=Bob Smith|FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|DEF_COMMENT=|PLF_COMMENT=some freeform text|';
I'm not very accomplished with JavaScript :(
I tried various things in JSFiddle using split() and match() but I just made a mess of it.
// Convert the template to an array of keys
const getKeys = str => str.split('|').map(entry => entry.split('=')[0]);
// Convert the data to an object
const toObj = str => Object.fromEntries(str.split('|').map(entry => entry.split('=')));
// Reconcile the data with the template
const compile = (templateStr, dataStr) => {
const keys = getKeys(templateStr);
const data = toObj(dataStr);
return keys.reduce((results, key) => {
if(key) results.push([key, data[key] ?? '']);
return results;
}, []);
};
// Convert the results back into a string
const toString = data => data.map(entry => entry.join('=')).join('|') + '|';
// And then a test
let template = 'LAWYER=|FIRM=|SUIT_DESCRIPTION=|DEF_COMMENT=|PLF_COMMENT=|';
let current = 'FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|PLF_COMMENT=some freeform text|LAWYER=Bob Smith';
console.log(toString(compile(template, current)));
Right now my code is looking for the words 'Cheese' or 'Bread' within a specific webpage, and if it finds either word it should display an alert. However, it only displays the alert if the first word is found (cheese). Any suggestions on how to fix it so that it will successfully look for more than one word?
var array = Array.from(document.getElementsByClassName('wide-content-host'))
.find(el => el.innerText.includes('Cheese', 'Bread'));
if (array){
alert("Word found!")
}
This is an obvious change, but we could put an OR operator inside of the statement to signify both of them, like so:
let array = Array.from(document.getElementsByClassName('wide-content-host'))
.find(el => el.innerText.includes('Cheese') || el.innerText.includes('Bread'));
if (array) alert('Word found!');
You could also do it a more elegant way, like so:
const conditions = ['Cheese', 'Bread'];
const array = Array.from(document.getElementsByClassName('wide-content-host'));
const results = array.find((el) => conditions.some(nEl => el.innerText.includes(nEl)));
if (results) alert('Word found!');
This one works by grabbing the array from the 'wide-content-host' class name, then looping through that array with another loop that is looping through the values of the conditions array. With all of these loops working together, it will check whether or not the elements include the conditions.
** Edit **
In order to make the methods work without case-sensitivity, you would need to make the search cases lowercase e.g. 'cheese' and 'bread', and you would need to make the strings that you are searching through completely lowercase also.
Here are the examples for case-insensitivity:
let array = Array.from(document.getElementsByClassName('wide-content-host'))
.find(el => el.innerText.toLowerCase().includes('Cheese') || el.innerText.toLowerCase().includes('Bread'));
if (array) alert('Word found!');
or
const conditions = ['cheese', 'bread'];
const array = Array.from(document.getElementsByClassName('wide-content-host'));
const results = array.find((el) => conditions.some(nEl => el.innerText.toLowerCase().includes(nEl)));
if (results) alert('Word found!');
This can be done with regular expressions
let elem = document.querySelector("section");
let entries = elem.innerHTML.match(/(cheese)|(bread)/gi);
if (entries.length > 0) {
alert(`Words were found: ${entries}`);
}
<section>
<p>Cheese Bread</p>
<p>cheeSE BREAD</p>
</section>
I am trying to get a list of repositories, that is my code does a search for repositories with a filter
The Javascript gets a result, with multiple items that contain the data for each repository that fit the filter using the URL: https://api.github.com/search/repositories?q=piccolowen+in:name.
I can do console.log(result.items[0].name) to get the first repository's name value, but I want get all of the repositories from the search printed to the console. I also want the code to be able to print all of the repositories and their values no matter how many repos fit the filter.
Here is the current code I want to add on to:
window.onload = func()
async function func() {
const url = 'https://api.github.com/search/repositories?q=piccolowen+in:name'
const response = await fetch(url);
const result = await response.json();
const apiresult = document.getElementById('thisisanid')
console.log(result)
}
Any ideas on how I could do this?
EDIT:
I found the answer to my problem using a while loop from this question: Get total number of items on Json object?
const resultLength = Object.keys(result.items).length
var arrnum = 0
while (arrnum < resultLength) {
//execute code
}
EDIT 2:
The code in my previous edit will crash a page. Still working on a solution for this huge bug.
Since results.items returns an array of objects, you can use Array.prototype.map to return all the item names, i.e.:
result.items.map(item => item.name)
If you want to simply filter out some properties, you can also do object destructuring. Let's say you want an array of items that only contain their name, id, and description, then you can do this:
result.items.map(({ name, id, description }) => ({ name, id, description }))
async function func() {
const url = 'https://api.github.com/search/repositories?q=piccolowen+in:name'
const response = await fetch(url);
const result = await response.json();
// Returns an array of item names
console.log(result.items.map(item => item.name));
// Returns an array of object with selected keys
console.log(result.items.map(({ name, id, description }) => ({ name, id, description })));
}
func();
The array has map function, which accepts a callback function. It iterate through all the elements and call the callback function and push data to the newly created array.
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
More:
Array.map
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
window.load = main();
const nameMapper = (item) => item.name;
const liMapper = (item) => `<li>${item.name}</li>`;
async function main() {
const url = "https://api.github.com/search/repositories?q=piccolowen+in:name";
const result = await fetch(url).then((x) => x.json());
const names = result.items.map(nameMapper);
const apiresult = document.getElementById("thisisanid");
apiresult.textContent = names;
const ul = document.getElementById("list");
ul.innerHTML = result.items.map(liMapper).join("");
}
#list li{
list-style: none;
padding: 5px 10px;
border: 1px solid black;
max-width: 400px;
}
<div id="thisisanid"></div>
<ul id="list">
</ul>
You can use like!
let list = document.getElementById('list');
let htmlTemplate = result.items.map(function(item) {
return item.name
}).join("")
list.insertAdjacentHTML('beforeend', htmlTemplate)
or you can use template literal
foe example
when you returning value in items.map()
return `${item.id}: ${item.name}`
I have an array of Groups s.t. each Group has many Users
I want to return all (unique) Users for a given array of Groups.
So far, I have
let actor = await User.query().findById(req.user.id).eager('groups') // find the actor requesting
let actor_groups = actor.groups // find all groups of actor
if (actor_groups.length > 1)
var actor_groups_users = actor_groups[0].user
for (let i = 0; i < actor_groups.length; i++) {
const actor_groups_users = actor_groups_users.concat(actor_groups[i]);
}
console.log('actor groups users is', actor_groups_users);
else
// return users from the first (only) group
which returns the error: actor_groups_users is not defined
Feels like a roundabout way to do this. Is there a way to just combine actor_groups into a single combined group?
Here we can cycle through, adding users if not already in the array, using .forEach() and .includes().
This is assuming that group.user is an Array of users.
let users = [];
// check that actor_groups has items in it
if (actor_groups && actor_groups.length > 1) {
// cycle through each actor_group
actor_groups.forEach( group => {
// check if we have a 'user' array with items in it
if (group.user && group.user.length > 1) {
// cycle through each user in the group
group.user.forEach( user => {
// check if we already have this user
// if not, add it to users
if (!users.includes(user)) {
users.push(user);
}
}
}
}
}
You can simply do this:
const allGroupsArrs = actor_groups.map(({ user }) => user);
const actor_groups_users = [].concat(...allGroupArrs);
Or, you could simply use the .flat() method, which is not yet officially part of the ES standard, but is on its way there and has browser support outside of IE:
const allGroupsArrs = actor_groups.map(({ user }) => user);
const actor_groups_users = allGroupArrs.flat();
Also, the above would result in duplicate values in actor_groups_users if there are people who are in multiple groups. You can remedy this (assuming the array elements are primitive values) using a Set:
const unique_users = [...new Set(actor_groups_users)];
The most efficient way I can think of is
const users = [...new Set([...actor_groups].flatMap(el => el.user))]
I used this example:
const actor_groups = [{user: ['ok','boom']}, {user: 'er'}]
console.log([...new Set([...actor_groups].flatMap(el => el.user))])
//output: ["ok", "boom", "er"]