I have this document in mongoDB:
{
"_id": {
"$oid": "628f739398580cae9c21b44f"
},
"events": [
{
"eventName": "Dans",
"eventText": "Danse",
"eventDate": "010101"
},
{
"eventName": "Spill",
"eventText": "Spille",
"eventDate": "020202"
}
],
"school": "Høyskolen Kristiania"
}
I am trying to get each event (name, text and date) in their own div, but can't seem to access each "block" by their own. They are supposed to be printed as one, and only where school matches, and my intention was to make different documents for each school and filter by query from there. That though, is not an issue. I am able to get all of them as one array of objects or like
{
[dev:server] _id: new ObjectId("628f739398580cae9c21b44f"),
[dev:server] events: [ [Object], [Object] ],
[dev:server] school: 'Høyskolen Kristiania'
[dev:server] }
My API currently looks like this:
Name of course is going to be sent in by userinfo, hardcoded for testing purposes.
router.get("/", async (req, res) => {
const name = "Høyskolen Kristiania";
const schools = await mongoDatabase
.collection("tempschool")
.find()
.toArray();
console.log(schools);
res.json(schools);
});
And my client:
function EventCard({ event }) {
const { eventName, eventDate, eventText } = event;
return (
<div>
<h1>{eventName}</h1>
<h3>{eventDate}</h3>
<div>{eventText}</div>
</div>
);
}
export function SchoolPage() {
const {loading, error, data} = useLoader(
async () => await fetchJSON("/api/schools")
);
const school = data;
if (loading) {
return <div>Loading...</div>;
}
if (error) {
return (
<div>Error</div>
);
}
return (
<div>
{school.map((event) => (
<div key={event.name}>
<EventCard event={event}/>
</div>
))}
</div>
);
}
I don't know if you've created tempschool as a MongooseSchema or not. You should though, you will then query it as
const school = await TempSchool.findOne({school: "Høyskolen Kristiania"});
school.events will then give you an array of objects. You will use it on front-end as
return(
<div>
school.events.map((event) => (
<div>
<h1>{event.eventName}</h1>
<h3>{event.eventDate}</h3>
<div>{event.eventText}</div>
</div>
)
)
</div>
);
Related
In Shopware App, I added a new tab in the category section.
I defined a few fields in there,
when I want to save data in custom fields in the category table, it works well. I use Subscribe for that.
But somewhere, I need to save data in a different table, .for example, the system_config table.
I need to know how to save data if the user clicks "save" at the header bar.
<template>
<div class="sas-category">
<sw-text-field
v-model="facebookTitle"
:label="$t('sasCategory.facebook.title.label')"
/>
</div>
<script>
export default {
data() {
return {
facebookTitle: null,
}
},
mounted() {
this.createdComponent()
},
updated() {
this.saveSystemConfigData()
},
methods: {
async createdComponent() {
this.category = await data.get({
id: 'sw-category-detail__category',
})
await this.getDataConfig()
},
/*
Get data from the system_config table
*/
async getDataConfig() {
let { data } = await systemConfigService.getConfigs()
let socialConfig = null
data = data.filter((item) =>
[CONFIGS.APP_SEO_SOCIAL + '_' + this.category.id].includes(
item.key
)
)
const socialConfigKey = [
CONFIGS.SOCIAL_FACEBOOK_TITLE,
]
if (data) {
socialConfig = data[0].value.filter(
(item) => !socialConfigKey.includes(item)
)
}
if (socialConfig) {
socialConfig.map((value) => {
switch (value.key) {
case CONFIGS.SOCIAL_FACEBOOK_TITLE:
this.facebookTitle = value.value
break
}
})
}
},
/*
For display data that save in the system_config table for each category
We should have a unique name because of that, we save the category id as key
*/
async saveSystemConfigData() {
const configs = [
{
key: CONFIGS.APP_SEO_SOCIAL + '_' + this.category.id,
value: [
{
key: CONFIGS.SOCIAL_FACEBOOK_TITLE,
value: this.facebookTitle,
},
],
},
]
//Storage data in the system_config table in the Shopware
await systemConfigService.saveConfigs(configs)
},
},
}
</script>
PS:It works if the user changes data in sw-text-field.but I need to save data when the user clicks on the save button in the header.
I have a schema in which in one of the field i wanted it to store array of values. The schema is given below:
const memberSchema=new mongoose.Schema({
id:{
type:String,
unique:true
},
prefCurrency:{
type:String,
default:'AUD',
required:false
},
});
In the front end part, The user will select multiple currencies and which can be stored in the prefCurrency field of schema. The front end code is given below:
export default function MemberInformation() {
const { t } = useTranslation();
const[memberData,setMemberData]=useState([]);
const [member,setMember]=useState({id:"",prefCurrency:""})
var name,valueV;
const handleInputs=e=>{
console.log("Updated ",member)
name=e.target.name;
valueV=e.target.value;
setMember({...member,[name]:valueV})
}
const postData= ()=>{
setMemberData({...memberData,...member})
const {id,prefCurrency}=member;
var UpdatedMemInfo ={id,prefCurrency};
axios.put('/memberInfoUpdate', UpdatedMemInfo)
.then( res => {
alert('Updated successfully!');
}
)
.catch(err => {
console.log(err.response);
alert('An error occurred! Try submitting the form again.');
});
}
useEffect(() => {
async function fetchBooks() {
const response = await fetch('/memberinfo');
const json = await response.json();
setMemberData(json.memberLogin);
setMember(json.memberLogin);
console.log(json.memberLogin)
}
fetchBooks();
},[]);
return (
<Form.Select aria-label="Floating label select example" name="prefCurrency" value={member.prefCurrency} onChange={e=>handleInputs(e)}>
<span><ReactCountryFlag countryCode="AU" svg style={myStyle}/></span>
<option value="AUD" name="prefCurrency">AUD</option>
<option value="CAD" name="prefCurrency">CAD</option>
<option value="CHF" name="prefCurrency">CHF</option>
<option value="CNY" name="prefCurrency">CNY</option>
</Form.Select>
<Button variant="success" onClick={()=>postData()}>
Save Changes
</Button>
)
}
As in the above code, only one value can be selected and stored into the MongoDB but i want select multiple values and store in the form of array in the prefCurrency field of the schema and then retrieve it from the database to display it. What will be the code changes here?
The API for posting the above data in database is given below:
router.put('/memberInfoUpdate', async (req, res) => {
const {id,prefCurrency}=req.body;
var _id = req.body.id;
var UpdatedMemInfo = {
id:id,
prefCurrency:prefCurrency
};
Member.findOneAndUpdate(_id, UpdatedMemInfo, { new: true }, function(
err,
UpdatedMemInfo
) {
if (err) {
console.log("err", err);
res.status(500).send(err);
} else {
console.log("success");
res.send(UpdatedMemInfo);
}
});
});
The above update API is just for one value in the prefCurrency field but i want to have multiple selected values in it.
The prefCurrency Schema would look like this for storing array values.
const memberSchema=new mongoose.Schema({
id:{
type:String,
unique:true
},
prefCurrency:{
type:Array,
default:'AUD',
required:false
},
});
And the query for updating the prefCurrency is
var UpdatedMemInfo = {
id:id,
prefCurrency:[prefCurrency]
};
This will take array of values and update it.
I want to fetch data from API and show frontend using react but I am getting error from frontend side which is (TypeError: answers.map is not a function ) so how can I solve this error --
MY CODE IS -
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
import { getPolls } from "../helper/coreapicalls";
const MainPoll = () => {
const [polls, setPoll] = useState([]);
const [error, seterror] = useState(false);
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([]);
useEffect(() => {
loadPoll();
}, []);
const loadPoll = () => {
getPolls().then((data) => {
if (data.error) {
seterror(data.error);
} else {
setPoll(data);
console.log(data);
}
});
};
// Handling user vote
// Increments the votes count of answer when the user votes
const handalchange = () => {
console.log("hello");
};
return (
<div className="">
<div className="container">
<h1 className="blog_heading">Poll's of the Day</h1>
<div className="row">
{polls.map((poll, index) => (
<div className="col-lg-4 col-12" key={index}>
<Poll
question={poll.question}
answers={poll.options.none}
onVote={handalchange}
/>
</div>
))}
</div>
</div>
</div>
);
};
export default MainPoll;
Data which I am getting from API is-
Here I have Question , 3 options how can I show to frontend
Error -
There is two little mistakes in the code that you show us:
the first One you imported import Polls from "./polls"; and you call <Poll noStorage question={poll.question} answers={poll.options} onVote={handleVote}/> just change Poll by Polls.
const [pollAnswers, setPollAnswers] = useState([...answers]); this didn't work because you need to pass a initial value for your state and answer is not yet initialize and accessible. just change useState([...answers]); by useState([]);
UPDATE:
you need to pass an array to answers props .
We can see in your console screenshot that the array of options has "none" as key so
try this : <Poll noStorage question={poll.question} answers={poll.options.none} onVote={handleVote}/> ("none" is a strange key...)
UPDATE
Your data object is not well formated to fit react-polls answers props.
in the npmjs doc of react-polls we can see an example of options and it's an array of object like this:
[
{ option: 'Yes', votes: 8 },
{ option: 'No', votes: 2 }
]
so based on the data console log that you add in your question it should looks like this:
[
{
createdAt: "2020-12-01T21:43:23:21.061Z",
options: {
none: [ { option: 'Yes', votes: 8 },
{ option: 'No', votes: 2 }],
student: ["12345678978945"],
teacher: ["7894567894231"]
},
question: "Are you student ot teacher",
updatedAt: "2020-12-01T21:43:23:21.061Z"
}
]
see a sandBox here working with your code (except getPolls()).
I think the issue come from the API.
i am fetching details from database through Id wanted to display that into the table, but for initial purpose i wanted to just display on browser without table and stuff.. am getting values.map is not a function but when I did console.log(values), got {title: "", description: "", tags: "", photo: "", loading: false, …}
createdBlog: ""
description: ""
error: ""
formData: ""
getaRedirect: false
loading: false
photo: ""
tags: ""
title: ""
proto: Object
what to do, please help
import React, { useState, useEffect } from "react";
import "../../styles.css";
import { getoneBlog } from "../helper/coreapicalls";
import ImageHelper from "../helper/ImageHelper";
const Fullblog = ({ match }) => {
const [values, setValues] = useState({
title: "",
description: "",
tags: "",
photo: "",
loading: false,
error: "",
createdBlog: "",
getaRedirect: false,
formData: "",
});
const {
title,
description,
tags,
loading,
error,
createdBlog,
getaRedirect,
formData,
} = values;
const preload = (blogId) => {
getoneBlog(blogId).then((data) => {
//console.log(data);
if (data.error) {
setValues({ ...values, error: data.error });
} else {
// preloadCategories();
setValues({
...values,
title: data.title,
description: data.description,
tags: data.tags,
formData: new FormData(),
});
}
});
};
console.log(values);
useEffect(() => {
preload(match.params.blogId);
}, []);
return (
<div>
<div className="py-md-5 py-3">
<div className="Fullblog ">
{values.map((fullblog, index) => {
return (
<div>
<h1 className="FullblogTittle">
Founder Leandra Medine Cohen announced the news to her
employees on a Zoom call earlier this week.
{fullblog.title}
</h1>
<p className="tags">tags </p>
<img
src="https://cdn.pixabay.com/photo/2020/10/17/17/41/girl-5662873_960_720.jpg"
className="FullblogImg"
alt="img"
/>
<ImageHelper />
<p className="description">
CULTURE How to Celebrate Halloween at Home This Year From
horror movie marathons to Halloween-themed drive-in features
to virtual pumpkin carving parties, here's how to celebrate
Halloween safely this year. By Pahull Bains Date October 22,
2020 With cases on the rise in certain regions of Ontario ’s A
Little Blurry. The livestream will be viewable on demand for
24 hours for ticket holders. Get your tickets here.
</p>
</div>
);
})}
</div>
</div>
</div>
);
};
export default Fullblog;
coreapicalls code-
// get all Blogs
export const getBlogs = () => {
return fetch(`${API}/blogs`, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((err) => console.log(err));
};
//get a Blog
export const getoneBlog = (blogId) => {
return fetch(`${API}blog/${blogId}`, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((err) => console.log(err));
};
You can use .map() function on an Array but your state looks to be set up as an Object rather than an array.
Check these lines:
{values.map((fullblog, index) => {
&
const [values, setValues] = useState({ ... }); // This is an object
Reference
The map() method creates a new array populated with the results of
calling a provided function on every element in the calling array.
So the issue is, you are trying the map() on an object that's why it is showing you the error.
You can only use .map() on Array variables, as mentioned before.
You can simply do this:
Object.keys(values), which will make an Array with the keys of your object.
Object.keys(values).map( keys => console.log(values[key]) )
You used object destructuring on values but there is no such method as Object.prototype.map...
You can loop over Object.values(values) with map or Object.keys(values) if you want to loop over the keys.
Code:
Object.values(values).map((fullblog, index) => {
// insert code here
});
I'm trying to build a search bar with a react frontend and node backend, that will let me search a customer ID from a mongoDB collection, then pull all of the data from a single document down from within the collection and display it on my react app.
Currently, I am just trying to get to get the single document bit to work, if this is possible. At the moment, it pulls down the entire collection.
My current Node code:
Search router
const express = require('express');
const app = express();
const tfiPaintCodesRouter = express.Router();
const PaintInfoSchema = require('../models/PaintInfoSchema.js');
tfiPaintCodesRouter.route('/get').get(function (req, res) {
const tfipaintcode = new PaintInfoSchema(req.body);
console.log(req.body)
tfipaintcode.save()
.then(tfipaintcode => {
res.json('Got data!!');
})
.catch(err => {
res.status(400).send("unable to get data");
console.log('CustomerID is required', err.res);
});
});
tfiPaintCodesRouter.route('/').get(function (req, res) {
PaintInfoSchema.find(function (err, tfipaintcodes){
if(err){
console.log('this is an error!', err.res);
}
else {
res.json(tfipaintcodes);
}
});
});
module.exports = tfiPaintCodesRouter;
Mongo schema using mongoose.
const mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator');
const Schema = mongoose.Schema;
// Create schema
const PaintInfoSchema = new Schema({
customerID: {
required: true,
index: true,
unique: true,
type: String
},
companyName: {
index: true,
type: String
},
curtainCodes: {
index: true,
type: String
},
sinageCodes: {
index: true,
type: String
},
Notes: {
index: true,
type: String
},
Method: {
index: true,
type: String
},
},{
collection: 'tfiPaintCodes'
});
PaintInfoSchema.plugin(uniqueValidator);
module.exports = mongoose.model('PaintInfoSchema', PaintInfoSchema)
My current react code is:
import React from 'react';
import { Form, FormGroup, Input, Container, Row, Col } from 'reactstrap';
import './Search.css'
import axios from 'axios'
class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
searchInfo: []
};
}
handleInputChange = (event) => {
event.preventDefault();
const { value } = event.target;
console.log('Value', value)
this.setState({
query: value
});
this.search(value);
};
search = query => {
axios.get('http://localhost:3001/getData')
.then(res =>{
const searchInfo = (res.data || []).map(obj => ({
company: obj.companyName,
sinage: obj.sinageCodes,
method: obj.Method,
notes: obj.Notes}));
this.setState({ searchInfo });
})
};
componentDidMount() {
this.search("");
}
render() {
return(
<Container>
<Form>
<Row>
<Col md={{ size: 6 ,offset: 3}}>
<FormGroup className="SearchBar">
<Input onChange={this.handleInputChange} type="search" name="search" id="exampleSearch" placeholder="search" />
</FormGroup>
</Col>
</Row>
</Form>
<ul>
{this.state.searchInfo.map(function(searchInfo, index){
return (
<div key={index}>
<h1>NAME: {searchInfo.company}</h1>
<p>{searchInfo.sinage}</p>
<p>{searchInfo.method}</p>
<p>{searchInfo.notes}</p>
</div>
)
}
)}
</ul>
</Container>
);
}
}
export default Search
The code above queries mongodb, then pulls down all of the data stored in my collection, here is an image of the returned data.
Data displayed in frontend
But i want to know if it is possible to just pull down one document in that collection, so it would just display one Name: and then the other 4 bits of data.
I have the data stored in Mlab, here is a screenshot of the documents stored in my collection.
data in mongodb
Is this possible? Thanks!
The best way is to pull only one document from the DB (if you don't need more in your case).
Mongoose, as any other ORM/ODM, gives you those options:
https://mongoosejs.com/docs/api.html#model_Model.findOne
With FindOne you can search for documents but get only one (aka. "the first found") document back.
If you need a fixed number of returned documents, you can use limit(10) to, for example, return only 10 documents.
Though it appears to me that your code-snippets don't show the exact segment where do the query in Mongoose, otherwise we could have shown you what to do in your own example.