I hope I can explain the question clearly. I need to create a few categories in category with <input type="checkbox"/>. Can you help how do it
{
"properties":{
"category":[
"0" : "category-1",
"1" : "category-2"
],
"image": "https://link...",
...
}
}
now I can only add one value at a time, but I need a lot
{
"properties":{
"category": "category-1",
"image": "https://link...",
...
}
}
const handleSubmit = (e) =>{
e.preventDefault();
const movie = {id, category, title, poster, rating, year, video, trailer, description};
fetch('http://localhost:8000/movies', {
method: 'POST',
headers: {"Content-Type" : "application/json" },
body: JSON.stringify(movie)
}).then(() => {
alert('Успешно добавился фильм!');
})
}
So if im understanding you correctly, you want to add multiple categories to the body of a POST endpoint? As long as your api handles an array for the “category”, then its pretty easy! But first, there are some things I see in your code:
In javascript, you don’t explicitly write the index of an array. You just write the item, for
example
const listOfStrings = [“string 1”, “string 2”]
const listOfObj = [{name: ‘Aj”}, {name: ‘bj’}]
It seems like you are implicitly passing in the properties for your “movie” object, just make sure that each property is defined somewhere above.
Now on to your question! What you want to do is the following:
Create a list of categories, make sure they match whatever the backend is expecting
create a state to track the selected categories
map through the array and render an input for each
assign each input props based on its indexed category
create a function that updates the selected state with a new category or a category removed
The key principles you'll need to research if youre unfamiliar with this are:
Javascript: map, filter
React: JSX,
Rendering lists
hooks (useState)
Code Example: https://codesandbox.io/s/jolly-moon-fbhs7c?file=/src/App.js
Related
I have two TaskList components that use the same query GET_TASKS.
Both use a different filter query variable which is passed down to them in props as queryVars.
I defined a standard merge function in type policies to merge the incoming and existing data together.
The TaskList component uses
const { data, fetchMore } = useQuery<Response, Variables>(GET_TASKS, { variables: queryVars })
to retrieve the data.
A Fetch more button has () => fetchMore({ variables: queryVars }) in the onClick attribute.
When I click on the Fetch more button on the left, the tasks on the right get updated as well, however, without its filter applied, so the data that come with Assigned to me filter are also put to the Assigned by me task list and vice versa.
The merge function basically rewrites every data object that uses the given query.
How do I tell Apollo to only update the data that is bound to the component where fetchMore is defined?
You should be able to add filter to the keyArgs property. This should create different cache results based on the filter.
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
tasks: {
keyArgs: ["filter"],
merge(existing, incoming, { args: { offset = 0 }}) {
//Custom merge
},
},
},
},
},
});
Edit to clarify:I have an object from an API response that I get using the mounted function, data is saved not displayed yet. I need to be able to filter that data by allowing a user to input text in an input box before showing it on the page, then find where that keyword was used in a specific key value(name). Then show the results on a page but include other key/value pairs from the api array. This is what the api response looks like:
class: (...)
facets: (...)
numberFound: (...)
results: Array(202)
[0 … 99]
0:
class: "SearchResult"
contentGuid: "7f19462f-6c25-43a9-bdb5-479f5f42fbde"
dateUpdated: "2018-03-27T16:46:31Z"
description: "Converting a Word Document to Adobe Acrobat PDF Learning Services Converting a Word Document to Adobe Acrobat PDF Enterprise Converting a Word Document to Adobe Acrobat PDF / Reference ..."
document: Object
documentGuid: "035f5c69-d406-4c16-86ca-de12773a0963"
documentId: 154424
documentVersionId: 44043
fileId: 74213
format: "PDF"
id: "Document#1#44043"
isFavorite: false
languages: "English"
name: "Converting a Word Document to Adobe Acrobat PDF"
numberOfIndexedCoobs: 0
numberOfSharedLinks: 1
packageType: "PDF"
previewId: 74213
publicLinkTokens: Array(1)
resourceType: "Other"
score: 0.0054571675
snippets: Object
updatedById: 994
updatedByName: "Michael"
versionName: "3"
For example if someone enters "Adobe" in the search box, I would need to search for the word "adobe" in the name value for the entire object, and only show the ones that have "abobe" somewhere in the name value.
My thought was to get the document name split it, then do an includes() to check for the search term. This works but I can't seem to figure out how to get it all to work together and get the results on the screen, plus get additional information, such as document Id from the original results. this is what I have so far:
async getResults() {
return axios
.get(this.url, {
headers: {
"Content-Type": "application/json",
"Bravais-prod-us-Context": this.getCookie(),
},
})
.then((res) => {
this.search = res.data;
this.search.results.forEach((doc) => {
this.results = doc.document.name
.toLowerCase()
.split(" ")
.includes(this.termSearch.toLowerCase());
console.log(doc.document.name.split(" "));
console.log(this.results);
});
})
.catch((error) => console.log(error));
},
I need to show the original title(some words and acronyms are capitalized) plus the doc id(for url links) and a description, all of this info is in the initial api response.
<div v-for="" v-bind:key="">
{{ ???? }}
</div>
That works in the console but how do I get this back together and on the screen?? Any help is appreciated, not looking for someone else to do my coding, just need some advice.
I would start by diving your logic. At the moment you have a single function that makes an api call and then searches through the results. It would be better suited to have the api call in a separate method so that if the user searches multiple times it doesn't call the api each time. We can easily solve this by adding an extra method that checks if the results object is populated and decides which methods to call.
Casting all strings to lowercase is a good idea to normalize the data. There might be other ways but this works for it's intended purpose. However, splitting a string is unecessary as the includes() method searches through the whole string. See the MDN docs for String.prototype.includes()
To search within an array you can use the filter() method, which will create a new array with all elements that pass the implemented test. See the MDN docs for Array.prototype.filter().
With this in hand, we can write our logic as:
async handleSearch(searchString) {
if (!this.results.length) {
this.getResults()
}
this.searchResults(searchString)
},
async getResults() {
return axios.get(this.url, {
headers: {
"Content-Type": "application/json",
"Bravais-prod-us-Context": this.getCookie(),
},
}).then((res) => {
this.results = res.data.results
}).catch((error) => console.error(error));
},
searchResults(searchString) {
this.filteredResults = this.results.filter(item => {
let name = item.name.toLowerCase();
let searchTerm = searchString.toLowerCase();
return this.name.includes(searchTerm)
})
}
Your input field will call the handleSearch() method, and then you can write you html as such:
<div v-for="result in filteredResults" :key="result.id">
<p>Name: {{result.name}}</p>
<p>Description: {{result.description}}</p>
</div>
I have a collection with an array field ("array") that stores _ids which reference another collection. I am using mongoose's .populate and can populate a specific array element using the string dot notation, e.g.
.populate({path: "array.4"})
but I would now like to populate the last element of the array. In an ideal world, "array.-1" would work but it does not. I have tried using populate's match property with something like:
.populate({
path: "array",
match: {
$arrayElemAt: {
$subtract: [
{
$size: "array"
},
1
]
}
},
})
but this doesn't work either (and I don't think is how it's supposed to be used at all!)
Is there any way to achieve this?
Try this.
User.find({},{"arrayObject": {$slice: -1})
.populate('arrayObject')
Not sure if this is precisely what you're looking for but there is an easy way to do that for a specific document, which could help you do that for multiple. Let's imagine that your document's name is User and the array field that stores those ObjectIds is hobbies. So a sample doc may look like this:
{
"_id": ObjectId("5a934e000102030405000000"),
"hobbies": [
ObjectId("5a934e000102030405000001"),
ObjectId("5a934e000102030405000002")
],
"name": "James"
}
You could populate the last element of the hobbies array for a specific user doing this:
User.findById('5a934e000102030405000000')
.then(user => {
user.populate(`hobbies.${user.hobbies.length - 1}`, (err, u) => {
console.log(u);
});
})
If you have multiple docs you want populated, I would do it like this fully realizing that depending on how many docs you have, this make be time consuming:
User.find()
.then(users => {
const promises = users.map(user =>
user.populate(`hobbies.${user.hobbies.length - 1}`).execPopulate()
)
Promise.all(promises).then(pop => {
console.log(pop); //All populated with only last element of hobbies array
})
})
I'm looking for a way to have an optimistic Ui delete an Item from a list.
The query for the list is:
myQuery{
Foo:{
Bar:{
id
}
}
delete mutation:
mutation deleteBar(input: barInput!){
deleteBarItem: (responds Boolean for success)
}
How do I structure the optimisticResponse?
deleteBarItem({
variables:{
barInput:{
id: idToBeDeleted
}
},
optimisticResponse:{
?????
},
update: (cache, { data}) => { ...manipulate the list in cache}
})
Here's a Medium article with one example for how to use OptimisticResponse for deleting an item from a list.
It'd be helpful to see your schema, but here's a working example from a toy to-do app I built with OptimisticResponse working for deleting items from the list:
optimisticResponse: {
__typename: "Mutation",
deleteResolution: {
__typename: "Resolution",
_id
}
}
You can verify your OptimisticResponse is working by setting your Network speed to Slow 3G in the dev console and ensuring that the item still gets removed immediately.
Side note - you can use filter in the update function instead of a boolean to cleanly create a new array with the item removed. Here's how I do this in the to-do app linked above, where _id is the id of the item to be removed that gets passed in as a prop to the DeleteResolution component:
resolutions = resolutions.filter(
resolution => resolution._id !== _id
);
Thanks to xadm for providing an example in the comments to reference
deleteBarItem({
variables:{
barInput:{
id: idToBeDeleted
}
},
optimisticResponse:{
deleteBarItem: true,
foo:{
id: idToBeDeleted,
__typename: "Bar"
}
},
update: (cache, { data}) => { ...manipulate the list in cache}
})
A couple key notes.
Cache: Uses __typename and id to reference objects. Using the optimistic ui to "delete" and Item you need to set the cache with an object that has no other information associated with it.
update: This function is run twice. Once with the optimistic results and then again when the mutation comes back. With my example of the mutation returning a boolean I added a filter to the list based on that boolean to remove deleted item from the list or leave it intact.
What I am trying to do
I am creating a social media app with react native and firebase. I am trying to call a function, and have that function return a list of posts from off of my server.
Problem
Using the return method on a firebase query gives me a hard to use object array:
Array [
Object {
"-L2mDBZ6gqY6ANJD6rg1": Object {
//...
},
},
]
I don't like how there is an object inside of an object, and the whole thing is very hard to work with. I created a list inside my app and named it items, and when pushing all of the values to that, I got a much easier to work with object:
Array [
Object {
//...
"key": "-L2mDBZ6gqY6ANJD6rg1",
},
]
This object is also a lot nicer to use because the key is not the name of the object, but inside of it.
I would just return the array I made, but that returns as undefined.
My question
In a function, how can I return an array I created using a firebase query? (to get the objects of an array)
My Code
runQ(group){
var items = [];
//I am returning the entire firebase query...
return firebase.database().ref('posts/'+group).orderByKey().once ('value', (snap) => {
snap.forEach ( (child) => {
items.push({
//post contents
});
});
console.log(items)
//... but all I want to return is the items array. This returns undefined though.
})
}
Please let me know if I'm getting your question correctly. So, the posts table in database looks like this right now:
And you want to return these posts in this manner:
[
{
"key": "-L1ELDwqJqm17iBI4UZu",
"message": "post 1"
},
{
"key": "-L1ELOuuf9hOdydnI3HU",
"message": "post 2"
},
{
"key": "-L1ELqFi7X9lm6ssOd5d",
"message": "post 3"
},
{
"key": "-L1EMH-Co64-RAQ1-AvU",
"message": "post 4"
}
...
]
Is this correct? If so, here's what you're suppose to do:
var items = [];
firebase.database().ref('posts').orderByKey().once('value', (snapshot) => {
snapshot.forEach((child) => {
// 'key' might not be a part of the post, if you do want to
// include the key as well, then use this code instead
//
// const post = child.val();
// const key = child.key;
// items.push({ ...post, key });
//
// Otherwise, the following line is enough
items.push(child.val());
});
// Then, do something with the 'items' array here
})
.catch(() => { });
Off the topics here: I see that you're using firebase.database().... to fetch posts from the database, are you using cloud functions or you're fetching those posts in your App, using users' devices to do so? If it's the latter, you probably would rather use cloud functions and pagination to fetch posts, mainly because of 2 reasons:
There might be too many posts to fetch at one time
This causes security issues, because you're allowing every device to connect to your database (you'd have to come up with real good security rules to keep your database safe)