I have POST function and it's post data to sharepoint list after that I need to refresh the page to show the data. I tried to run GET function put it Didn't Print the data
after clicking on arrow 1 POST function start and send the data to sharepoint list
after the data should be visible here with the 3 but it didn't show I need to refresh the page to show the data
-I got an idea that to print temporary UseState to show the data but I dont know how to do it
here is my latest code
function Feed(props) {
const [data,setdata] = useState(props)
return (
<div>
{data.data.map((item) => {
var spFormated = Moment(item.fields.Date).format('MM/DD/YYYY')
if (formated == spFormated ) {
if(item.fields.Hours<=2){
return(
<React.Fragment key={item.id}>
<div className="taskcolorback-div" />
<button className="taskcolor-button" />
<input className="tasktext-b" defaultValue={Moment(item.fields.Date).format('MM/DD/YYYY')}></input>
<button className="taskwhite-button" />
<b className="timeinline">{item.fields.Hours}Hr</b>
<img className="vector-icon" alt="" src="icons8-chevron-right-64.png" />
</React.Fragment>)
}
else if(item.fields.Hours==3){
return(
<React.Fragment key={item.id}>
<div className="taskcolorback-div3" />
<button className="taskcolor-button3" />
<input className="tasktext-b3" defaultValue={Moment(item.fields.Date).format('MM/DD/YYYY')}></input>
<button className="taskwhite-button3" />
<b className="timeinline3">{item.fields.Hours}Hr</b>
<img className="vector-icon3" alt="" src="icons8-chevron-right-64.png" />
</React.Fragment>)
}
else if(item.fields.Hours==4){
return(
<React.Fragment key={item.id}>
<div className="taskcolorback-div4" />
<button className="taskcolor-button4" />
<input className="tasktext-b4" defaultValue={Moment(item.fields.Date).format('MM/DD/YYYY')}></input>
<button className="taskwhite-button4" />
<b className="timeinline4">{item.fields.Hours}Hr</b>
<img className="vector-icon4" alt="" src="icons8-chevron-right-64.png" />
</React.Fragment>)
}
else if(item.fields.Hours>=5){
return(
<React.Fragment key={item.id}>
<div className="taskcolorback-div5" />
<button className="taskcolor-button5" />
<input className="tasktext-b5" defaultValue={Moment(item.fields.Date).format('MM/DD/YYYY')}></input>
<button className="taskwhite-button5" />
<b className="timeinline5">{item.fields.Hours}Hr</b>
<img className="vector-icon5" alt="" src="icons8-chevron-right-64.png" />
</React.Fragment>)
}
return(
<>
<React.Fragment key={item.id}>
<div className="taskcolorback-div" />
<button className="taskcolor-button" />
<input className="tasktext-b" defaultValue={Moment(item.fields.Date).format('MM/DD/YYYY')}></input>
<button className="taskwhite-button" />
<b className="timeinline">{item.fields.Hours}Hr</b>
<img className="vector-icon" alt="" src="icons8-chevron-right-64.png" />
</React.Fragment>
</>
)
}
// 👇️ render nothing
return console.log("null");
})}
</div>
);
}
Note: The map function will get the data from API
import { graphConfig,graphConfigh } from "./authConfig";
/**
* Attaches a given access token to a MS Graph API call. Returns information about the user
* #param accessToken
*/
export async function callMsGraph(accessToken) {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers
};
return fetch(graphConfig.graphMeEndpoint, options)
.then(response => response.json())
.catch(error => console.log(error));
}
//-------------------------------
export async function PostData(accessToken) {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "post",
headers: {
'Authorization': bearer,
'Content-Type': 'application/json'
},
body: JSON.stringify({fields: {Title: 'TEST',Date: '08/13/2022',Hours:"3"}})
};
return fetch(graphConfigh.graphMeEndpointh, options)
.catch(error => console.log(error));
}
Related
My application doesn't redirect me to /quiz page after submit the form, browser always show Cannot POST /quiz.
My goal is: i need to redirect from /form page to /quiz page with all the data that has been submitted.
Should i add a route for /quiz?
Frontend:
form.jsx:
const submit = async (e) => {
/* e.preventDefault(); */
await FormService.store(storedata)
.then((res) => {
console.log(res);
})
.catch((err) => {
return err;
});
};
return (
<div className="container">
<div className="header">
<div className="title">
<h1>Apply for a Position :</h1>
</div>
</div>
<Divider style={{ maxWidth: '1000px', marginLeft: '250px' }} />
<div id="content">
<div id="formWrapper">
<form
id="msform"
method="post"
action="/quiz"
enctype="multipart/form-data"
>
<fieldset id="fieldset3">
<h2 class="fs-title">
Please complete the form below for a position with us.
</h2>
<h3 class="fs-subtitle">Reference 0001</h3>
{/* <div class="fs-error"></div> */}
<div class="wrapper">
<label for="CV">
Upload CV <span>*</span>:
</label>
<input
type="file"
name="myFile"
id="cv"
onChange={handleCVChange}
accept="application/msword, application/pdf, .docx"
placeholder="Cover Letter"
required
/>
<label for="coverLetter">Cover Letter :</label>
<textarea
type="text"
name="coverLetter"
value={storedata.coverLetter}
onChange={handleChange}
id="coverLetter"
placeholder="Your Cover Letter"
/>
</div>
<br />
<input
type="submit"
name="submit"
class="submit action-button"
value="Submit"
onClick={submit}
/>
</fieldset>
</form>
</div>
</div>
</div>
);
};
export default Form;
quiz.jsx:
import React, { useState, useContext } from 'react'
import { QuizContext } from '../Helpers/Contexts'
import { Questions } from '../Helpers/QuestionBank'
function Quizz() {
const { score, setscore, setGameState } = useContext(QuizContext)
const [currQuestion, setcurrQuestion] = useState(0) //state de numero de current question: 0/1/2
const [optionChosen, setoptionChosen] = useState("") //state de l'option choisi: A ou B ou C ou D
const nextQuestion = () => {
if (Questions[currQuestion].answer === optionChosen) {
setscore(score + 1);
}
//alert(score);
setcurrQuestion(currQuestion + 1);
}
const finishQuiz = () => {
if (Questions[currQuestion].answer === optionChosen) {
setscore(score + 1);
}
setGameState("endScreen")
}
return (
<div className='Quiz'>
<h1>{Questions[currQuestion].prompt}</h1>
<div className='options'>
<button onClick={() => setoptionChosen("A")}>{Questions[currQuestion].optionA}</button>
<button onClick={() => setoptionChosen("B")}>{Questions[currQuestion].optionB}</button>
<button onClick={() => setoptionChosen("C")}>{Questions[currQuestion].optionC}</button>
<button onClick={() => setoptionChosen("D")}>{Questions[currQuestion].optionD}</button>
</div>
{currQuestion === Questions.length - 1
?
(
<button onClick={finishQuiz}>Finish Quiz</button>
)
:
(
<button onClick={nextQuestion}>Next Question</button>
)}
</div>
)
}
export default Quizz
backend:
formRoute.js:
const express = require('express')
const router = express.Router()
const FormController = require('../controllers/FormController')
const upload = require('../Middleware/upload')
router.post('/store', upload.single('cv'), FormController.store)
module.exports = router
Formcontroller.js:
const form = require('../models/FormModel')
module.exports = {
store: (req, res, next) => {
let candidate = new form({
coverLetter: req.body.coverLetter,
cv: req.body.cv
})
if (req.file) {
candidate.cv = req.file.path
}
candidate.save()
.then(response => {
res.json({
success: true,
message: 'Candidate added successfully!',
data: candidate,
})
})
.catch(error => {
res.json({
success: false,
message: 'An error occured!',
error: error,
})
})
}
}
src/App.js:
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './views/Home/Home';
import Formulaire from './views/Form/Formulaire';
import Quiz from './views/Quiz/Quiz';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/form" element={<Formulaire />} />
<Route path="/quiz" element={<Quiz />} />
</Routes>
</BrowserRouter>
);
}
export default App;
First install react-router-dom to your project
Then Replace your form.jsx from this
Form.jsx
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
const submit = async (e) => {
/* e.preventDefault(); */
await FormService.store(storedata)
.then((res) => {
console.log(res);
})
.catch((err) => {
return err;
});
};
function gotoQuiz() {
navigate('/quiz')
}
return (
<div className="container">
<div className="header">
<div className="title">
<h1>Apply for a Position :</h1>
</div>
</div>
<Divider style={{ maxWidth: '1000px', marginLeft: '250px' }} />
<div id="content">
<div id="formWrapper">
<form
onSubmit={gotoQuiz}
id="msform"
method="post"
enctype="multipart/form-data"
>
<fieldset id="fieldset3">
<h2 class="fs-title">
Please complete the form below for a position with us.
</h2>
<h3 class="fs-subtitle">Reference 0001</h3>
{/* <div class="fs-error"></div> */}
<div class="wrapper">
<label for="CV">
Upload CV <span>*</span>:
</label>
<input
type="file"
name="myFile"
id="cv"
onChange={handleCVChange}
accept="application/msword, application/pdf, .docx"
placeholder="Cover Letter"
required
/>
<label for="coverLetter">Cover Letter :</label>
<textarea
type="text"
name="coverLetter"
value={storedata.coverLetter}
onChange={handleChange}
id="coverLetter"
placeholder="Your Cover Letter"
/>
</div>
<br />
<input
type="submit"
name="submit"
class="submit action-button"
value="Submit"
onClick={submit}
/>
</fieldset>
</form>
</div>
</div>
</div>
);
};
export default Form; ````
I'm learning React and atm i'm making a crud App for Employee Data. Now the problem I'm having is that when i click on Add New button or Update button my component loads for respective features but my old component which is my Table of Data for all my employees stays open along with the new component. I want my Table of data to be disabled or hidden until my New Employee is added or old employee is updated on submission but i'm unable to do that... I made the AddNew.js for adding new employees, UpdateMember.js for updating old employees and then imported these components in my Table.js file which is then returned in the App.js component
The update component loads right on the spot of the update button itself which is another problem for me right now.
almost same is happening with Update even worse with this one
AddNew.js
function AddNew() {
const [list, setList] = useState(null);
const [Name, setName] = useState("");
const [Department, setDepartment] = useState("");
const [Salary, setSalary] = useState("");
const Data = {
name: Name,
department: Department,
salary: Salary,
};
const PostData = () => (event) => {
let header = new Headers();
header.append("Content-Type", "application/json");
// header.append("Accept", "application/json");
//
return (
fetch(PostUrl, {
method: "POST",
headers: header,
body: JSON.stringify(Data),
})
///
.then(() => {
fetch(BaseUrl, { method: "GET", headers: header })
//
.then((response) => response.json())
.then((result) => {
console.log(result);
setList(result);
});
})
);
};
return (
<div>
<form onSubmit={PostData}>
<h2>Add New Members</h2>
<span>* All fields are required</span>
<div className="outerDiv">
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="name"
placeholder="Name"
onChange={(event) => setName(event.target.value)}
/>
</div>
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="Department"
placeholder="Department"
onChange={(event) => setDepartment(event.target.value)}
/>
</div>
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="Salary"
placeholder="Salary"
onChange={(event) => setSalary(event.target.value)}
/>
</div>
<input className="btn btn-primary" type="submit" value="Save" />
</div>
</form>
</div>
);
}
export default AddNew;
UpdateMember.js
const UpdateRow = () => (event) => {
const PutData = {
name: Name,
department: Department,
salary: Salary,
};
console.log("Update Clicked");
let header = new Headers();
header.append("Content-Type", "application/json");
header.append("Accept", "application/json");
fetch(PutUrl, {
method: "PUT",
headers: header,
body: JSON.stringify(PutData),
})
.then((response) => response.json())
.then((response) => console.log(response))
.then(() => {
fetch(BaseUrl, { method: "GET", headers: header })
.then((res) => res.json())
.then((result) => {
setList(result);
});
});
};
return (
<div>
<form onSubmit={UpdateRow}>
<span className="text">* All fields are required</span>
<hr />
<div>
<h2>Update Information</h2>
<div className="outerDiv">
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="name"
placeholder="Name"
onChange={(event) => setName(event.target.value)}
/>
</div>
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="Department"
placeholder="Department"
onChange={(event) => setDepartment(event.target.value)}
/>
</div>
<div className="innerDiv">
<input
type="text"
autoComplete="off"
name="Salary"
placeholder="Salary"
onChange={(event) => setSalary(event.target.value)}
/>
</div>
<button
style={{ float: "right" }}
className="button btn-warning"
type="submit"
>
Update
</button>
</div>
</div>
</form>
</div>
);
}
export default UpdateMember;
Table.js
function Table() {
//
const [list, setList] = useState([]);
useEffect(() => {
let mounted = true;
getList().then((items) => {
if (mounted) {
setList(items);
}
});
return () => (mounted = false);
}, []);
//
const DeleteRow = (id) => (event) => {
let header = new Headers();
header.append("Content-Type", "application/json");
header.append("Accept", "application/json");
return fetch(DeleteUrl + id, { method: "DELETE", headers: header }).then(
() => {
fetch(BaseUrl, { method: "GET", headers: header })
.then((response) => response.json())
.then((result) => {
console.log(result);
setList(result);
});
}
);
};
//
return (
<div>
<h1>Employees Data</h1>
<Router>
<Link to="/Addnew" target="_blank">
<button
style={{ float: "right" }}
className="button btn-primary LinkButton"
>
Add New
</button>
</Link>
<Route path="/AddNew">
<AddNew />
</Route>
</Router>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Department</th>
<th>Salary</th>
<th>Actions</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{list.map((item) => (
<tr key={item.id}>
<td>
<center>{item.id}</center>
</td>
<td>
<center>{item.name}</center>
</td>
<td>
<center>{item.department}</center>
</td>
<td>
<center>{item.salary}</center>
</td>
<td>
<center>
<button
// key={item.id}
className="button btn-danger"
onClick={DeleteRow(item.id)}
>
Delete
</button>
</center>
</td>
<td>
<center>
<Router>
<Link to="/UpdateMember">
<button className="button btn-warning LinkButton">
Update
</button>
</Link>
<Switch>
<Route path="/UpdateMember">
<UpdateMember id={item.id} />
</Route>
</Switch>
</Router>
</center>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default Table;
App.js
function App() {
return (
<Table />
);
}
export default App;
I think that some conditional rendering could help you out with the problem.
Check it out here.
You can create a new variable called isLoading which will be set to true when you start a fetch and false after the fetch has finished. Then after that you can use it to check if isLoading is true, if it is true, do not show the table (conditional rendering)
And another suggestion would be creating a spinner to show when loading is true and hide when it is false, so that the user will know that it is loading.
how to use search filter: React?
I tried the below method to use search effect in reactjs but the result is not coming in my case. I think I have made a silly mistake somewhere, it would be great if anybody could figure out what I'm trying to solve is.
API end-point URL: http://localhost:8000/api/v1/post_list?search=test
function PostListSearch() {
const [posts, setPost] = useState([]);
const [userId, setUserId] = useState([]);
let signal = axios.CancelToken.source();
function handleChange(event) {
setUserId(event.target.value);
}
function handleClick(event) {
axios
.get(`http://localhost:8000/api/v1/post_list?search=${userId}`, {
cancelToken: signal.token
})
.then(res => {
const posts = res.data;
setPost(posts);
})
.catch(err => {
console.log(err);
});
}
return (
<React.Fragment>
<div class="theme-layout">
<div class="topbar stick">
<div class="top-area">
<div class="top-search">
<form>
<input
type="text"
name="search"
onChange={handleClick}
placeholder="Search keyword"
/>
<button data-ripple>
<i class="ti-search"></i>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="row">
{posts.map(post => (
<ul key={post.id}>
<div class="col-lg-8 col-xl-9">
<img src={post.image} alt="" class="img-fluid" />
<h3>{post.title}</h3>
</div>
</ul>
))}
</div>
</React.Fragment>
);
}
export default PostListSearch;
function PostListSearch() {
const [posts, setPost] = useState([]);
const [userId, setUserId] = useState([]);
let signal = axios.CancelToken.source();
function handleChange(event) {
setUserId(event.target.value);
}
function handleClick(event) {
event.preventDefault()
axios
.get(`http://localhost:8000/api/v1/post_list?search=${userId}`, {
cancelToken: signal.token
})
.then(res => {
const posts = res.data;
setPost(posts);
})
.catch(err => {
console.log(err);
});
}
return (
<React.Fragment>
<div class="theme-layout">
<div class="topbar stick">
<div class="top-area">
<div class="top-search">
<form>
<input
type="text"
name="search"
onChange={handleChange}
placeholder="Search keyword"
/>
<button data-ripple onClick={handleClick}>
<i class="ti-search"></i>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="row">
{posts.map(post => (
<ul key={post.id}>
<div class="col-lg-8 col-xl-9">
<img src={post.image} alt="" class="img-fluid" />
<h3>{post.title}</h3>
</div>
</ul>
))}
</div>
</React.Fragment>
);
}
export default PostListSearch;
try this out bro :D
I believe you can update your map logic and state initialisation as follows. Just copy paste the code as it is and try with both the approaches I have mentioned.
function PostListSearch() {
const [posts, setPost] = useState([]);
const [userId, setUserId] = useState(""); // CHANGE HERE
let signal = axios.CancelToken.source();
function handleChange(event) {
setUserId(event.target.value);
}
function handleClick(event) {
axios
.get(`http://localhost:8000/api/v1/post_list?search=${userId}`, {
cancelToken: signal.token
})
.then(res => {
const posts = res.data;
setPost(posts);
})
.catch(err => {
console.log(err);
});
}
return (
<React.Fragment>
<div class="theme-layout">
<div class="topbar stick">
<div class="top-area">
<div class="top-search">
<form>
<input
type="text"
name="search"
onChange={handleChange}
placeholder="Search keyword"
/>
<button data-ripple onClick={handleClick}>
<i class="ti-search"></i>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="row">
{
posts.map((post) => {<ul key={post.id}>
<div class="col-lg-8 col-xl-9">
<img src={post.image} alt="" class="img-fluid" />
<h3>{post.title}</h3>
</div>
</ul>})
}
</div>
</React.Fragment>
);
}
export default PostListSearch;
Another solution could be to keep initialistion as it is and try to push value in array. For this I have done changes in handleChange method
function PostListSearch() {
const [posts, setPost] = useState([]);
const [userId, setUserId] = useState([]);
let signal = axios.CancelToken.source();
function handleChange(event) {
let currUser = userId;
currUser.push(event.target.value)
setUserId(currUser );
}
function handleClick(event) {
axios
.get(`http://localhost:8000/api/v1/post_list?search=${userId}`, {
cancelToken: signal.token
})
.then(res => {
const posts = res.data;
setPost(posts);
})
.catch(err => {
console.log(err);
});
}
return (
<React.Fragment>
<div class="theme-layout">
<div class="topbar stick">
<div class="top-area">
<div class="top-search">
<form>
<input
type="text"
name="search"
onChange={handleChange}
placeholder="Search keyword"
/>
<button data-ripple onClick={handleClick}>
<i class="ti-search"></i>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="row">
{
posts.map((post) => {<ul key={post.id}>
<div class="col-lg-8 col-xl-9">
<img src={post.image} alt="" class="img-fluid" />
<h3>{post.title}</h3>
</div>
</ul>})
}
</div>
</React.Fragment>
);
}
export default PostListSearch;
I believe anyone of the above solution should work.
I am using Contentful as external container for my images.
I am building a boat visualizer using AISHub. All the vessels I am interested are injected into a table. When I click on the table I locate the marker (vessel) on the map and the image of that vessel pops up on a sidebar on the right of the map.
The problem I have is that I should also visualize the image of the vessel, but unfortunately I only visualize a weird icon as shown below:
Below the code I have so far:
import React from 'react';
import { Card, CardTitle, CardSubtitle, CardText, CardBody, CardImg } from 'reactstrap';
import '../components/SideBar.css';
import { Link } from 'react-router-dom';
import Client from '../Contentful';
class Sidebar extends React.Component {
state = {
ships: []
};
async componentDidMount() {
let response = await Client.getEntries({
content_type: 'cashmanCards'
});
const ships = response.items.map((item) => {
const { name, slug, type, company, description, images, companylogo } = item.fields;
return {
name,
slug,
type,
company,
description,
images,
companylogo
};
});
this.setState({
ships
});
}
getFilteredShips = () => {
if (!this.props.activeShip) {
return this.state.ships;
}
return this.state.ships.filter((ship) => this.props.activeShip.name.toLowerCase() === ship.name.toLowerCase());
};
render() {
return (
<div className="map-sidebar">
{this.props.activeShipTypes}
<pre>
{this.getFilteredShips().map((ship) => (
<Card className="mb-2">
<CardImg />
<CardBody>
<div className="row">
{/* <div className="column"> */}
<img className="image-sizing-primary" src={ship.companylogo} alt="shipImage" />
</div>
<div>
<img className="image-sizing-secondary" src={ship.images} alt="shipImage" />
</div>
<CardTitle>
<h3 className="thick">{ship.name}</h3>
</CardTitle>
<CardSubtitle>{ship.type}</CardSubtitle>
<CardText>
<br />
<h6>Project Details</h6>
<p>For a description of the project view the specification included</p>
</CardText>
<div class="btn-toolbar">
<SpecsButton />
<Link to="/vessels/Atchafalaya" className="btn btn-primary">
Go to vessel
</Link>
</div>
</CardBody>
</Card>
))}
</pre>
</div>
);
}
}
export default Sidebar;
EDITS:
class Sidebar extends React.Component {
state = {
ships: []
};
async componentDidMount() {
let response = await Client.getEntries({
content_type: 'cashmanCards'
});
const ships = response.items.map((item) => {
const { name, slug, type, company, description, images, companylogo } = item.fields;
return {
name,
slug,
type,
company,
description,
images,
companylogo
};
});
this.setState({
ships
});
}
getFilteredShips = () => {
if (!this.props.activeShip) {
return this.state.ships;
}
return this.state.ships.filter((ship) => this.props.activeShip.name.toLowerCase() === ship.name.toLowerCase());
};
{this.getFilteredShips().map((ship) => (
console.log(ship);
return (
<div className="map-sidebar">
<Card className="mb-2">
<CardImg />
<CardBody>
<div className="row">
<img className="image-sizing-primary" src={ship.companylogo} alt="shipImage" />
</div>
<div>
<img className="image-sizing-secondary" src={ship.images} alt="shipImage" />
</div>
<CardTitle>
<h3 className="thick">{ship.name}</h3>
</CardTitle>
<CardSubtitle>{ship.type}</CardSubtitle>
<CardText>
<br />
<h6>Project Details</h6>
<p>For a description of the project view the specification included</p>
</CardText>
<div class="btn-toolbar">
<SpecsButton />
<Link to="/vessels/Atchafalaya" className="btn btn-primary">
Go to vessel
</Link>
</div>
</CardBody>
</Card>
</div>
)))}
}
export default Sidebar;
EDITS 2:
class Sidebar extends React.Component {
state = {
ships: []
};
async componentDidMount() {
let response = await Client.getEntries({
content_type: 'cashmanCards'
});
const ships = response.items.map((item) => {
const { name, slug, type, company, description, images, companylogo } = item.fields;
return {
name,
slug,
type,
company,
description,
images,
companylogo
};
});
this.setState({
ships
});
}
getFilteredShips = () => {
if (!this.props.activeShip) {
return this.state.ships;
}
return this.state.ships.filter((ship) => this.props.activeShip.name.toLowerCase() === ship.name.toLowerCase());
};
{this.getFilteredShips().map((ship) => {
console.log(ship);
render() {
return (
<Card className="mb-2">
<CardImg />
<CardBody>
<div className="row">
{/* <div className="column"> */}
<img className="image-sizing-primary" src={ship.companylogo} alt="shipImage" />
</div>
<div>
<img className="image-sizing-secondary" src={ship.images} alt="shipImage" />
</div>
<CardTitle>
<h3 className="thick">{ship.name}</h3>
</CardTitle>
<CardSubtitle>{ship.type}</CardSubtitle>
<CardText>
<br />
<h6>Project Details</h6>
<p>For a description of the project view the specification included</p>
</CardText>
<div class="btn-toolbar">
<SpecsButton />
<Link to="/vessels/Atchafalaya" className="btn btn-primary">
Go to vessel
</Link>
</div>
</CardBody>
</Card>
)
}
})}
}
export default Sidebar;
Below a print screen on how Contentful is structured:
What I have done so far:
1) I was able to implement the table click event as well as finding the marker (vessel) and show its card on the right of a sidebar, and thought that it would have been easy to finally show the vessel image. Unfortunately the implementation does not show the image.
I should mention that I used reactstrap Cards.
Maybe there is an error in how Contentful is reading the image?
2) After researching more this problem I came across this post which was useful. The problem was that the image uploaded was local, I have an image that is external on an external container.
Thanks for pointing in the right direction.
here you go
import React from 'react';
import { Card, CardTitle, CardSubtitle, CardText, CardBody, CardImg } from 'reactstrap';
import '../components/SideBar.css';
import { Link } from 'react-router-dom';
import Client from '../Contentful';
class Sidebar extends React.Component {
state = {
ships: []
};
async componentDidMount() {
let response = await Client.getEntries({
content_type: 'cashmanCards'
});
const ships = response.items.map((item) => {
const { name, slug, type, company, description, images, companylogo } = item.fields;
return {
name,
slug,
type,
company,
description,
images,
companylogo
};
});
this.setState({
ships
});
}
getFilteredShips = () => {
if (!this.props.activeShip) {
return this.state.ships;
}
return this.state.ships.filter((ship) => this.props.activeShip.name.toLowerCase() === ship.name.toLowerCase());
};
render() {
return (
<div className="map-sidebar">
{this.props.activeShipTypes}
<pre>
{this.getFilteredShips().map((ship) => {
console.log(ship);
return (
<Card className="mb-2">
<CardImg />
<CardBody>
<div className="row">
{/* <div className="column"> */}
<img className="image-sizing-primary" src={ship.companylogo} alt="shipImage" />
</div>
<div>
<img className="image-sizing-secondary" src={ship.images} alt="shipImage" />
</div>
<CardTitle>
<h3 className="thick">{ship.name}</h3>
</CardTitle>
<CardSubtitle>{ship.type}</CardSubtitle>
<CardText>
<br />
<h6>Project Details</h6>
<p>For a description of the project view the specification included</p>
</CardText>
<div class="btn-toolbar">
<SpecsButton />
<Link to="/vessels/Atchafalaya" className="btn btn-primary">
Go to vessel
</Link>
</div>
</CardBody>
</Card>
)
})}
</pre>
</div>
);
}
}
export default Sidebar;
Ok so here's my code:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
var uuid = require("uuid-v4");
// Generate a new UUID
var myUUID = uuid();
// Validate a UUID as proper V4 format
uuid.isUUID(myUUID); // true
var questionNum = 0;
class App extends Component {
constructor(props) {
super(props);
this.state = {
key: uuid(),
title: "",
author: "",
questions: [],
answers: []
};
this.handleChange = this.handleChange.bind(this);
this.addQuestion = this.addQuestion.bind(this);
this.removeItem = this.removeItem.bind(this)
}
componentDidMount() {
// componentDidMount() is a React lifecycle method
this.addQuestion();
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
removeItem (index) {
questionNum--;
this.setState(({ questions }) => {
const mQuestions = [ ...questions ]
mQuestions.splice(index, 1)
return { questions: mQuestions }
})
this.setState(({ answers }) => {
const mAnswers = [ ...answers]
mAnswers.splice(index, 4)
return { answers: mAnswers}
})
console.log(
"answers",
this.state.answers,
"questions",
this.state.questions,
questionNum,
this.state.title,
this.state.author
);
}
addQuestion() {
questionNum++;
this.setState(previousState => {
const questions = [
...previousState.questions,
<input
type="text"
onChange={this.handleChange}
name="question"
key={uuid()}
/>
];
const answers = [
...previousState.answers,
];
for (var i = 0; i < 4; i++) {
answers.push(
<input
type="checkbox"
name={uuid()}>
<input
type="text"
onChange={this.handleChange}
name={uuid()}
/>
</input>
);
}
return { questions, answers };
});
console.log(
"answers",
this.state.answers,
"questions",
this.state.questions,
questionNum,
this.state.title,
this.state.author
);
}
render() {
return (
<div className="App">
<div>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Quiz Form 3.0</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
<div className="formDiv">
<form>
<div className="Intro">
Give your Quiz a title:{" "}
<input
type="text"
value={this.state.title}
onChange={this.handleChange}
name="title"
/>
<br />
Who's the Author?{" "}
<input
type="text"
value={this.state.author}
onChange={this.handleChange}
name="author"
/>
<br />
<br />
</div>
<div className="questions">
<div className="questions">
Now let's add some questions... <br />
<ol>
{this.state.questions.map(question => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<input type="text" key={uuid()} onChange={this.handleChange} />
))}
</div>
</li>
);
})}
</ol>
</div>
{
// This is what it would look like for the structure
// I proposed earlier.
// this.state.questions.map((question) {
// return (
// <div>{question.quesion}</div>
// {
// question.answers.map((answer) => {
// return (<div>{answer}</div>);
// })
// }
// );
// })
// This would output all questions and answers.
}
</div>
</form>
<button id="addQuestionButton" onClick={this.addQuestion}>Add Question</button>
{ this.state.questions.map((question, index) => {
return <button key={uuid()} onClick={ () => this.removeItem(index) }>Remove Question</button>
}) }
</div>
</div>
);
}
}
export default App;
Ok so here's a link to a quick video demonstrating what it does as of now. In the video you can see the Remove Question buttons that are created (at the bottom of the form) each time a question is added. I would like to have each question's Remove Question button be next to it/in the same div. I'm not entirely sure how I would go about doing this. Any thoughts?
UPDATE: Ok so I have put the buttons inside of the same div with the actual question, but I realized that i am adding a button for each object in the array. Which means that when a question is added a button to remove it is added to every question on the form. I need to make it so it does not .map this. I'm not entirely sure what other function I will do for this, maybe I don't even need a function. I will try my best to work it out. Here's the updated code (some of it):
<div className="questions">
Now let's add some questions... <br />
<ol>
{this.state.questions.map(question => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
{
this.state.questions.map((question, index) => {
return <button key={uuid()} onClick={ () => this.removeItem(index) }>Remove Question</button>
})
}
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<div>
<input type="checkbox" />
<input type="text" key={uuid()} onChange={this.handleChange} />
</div>
))}
</div>
</li>
);
})}
</ol>
</div>
Something like this...
<ol>
{this.state.questions.map((question, index) => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
<button onClick={ () => this.removeItem(index) }>
Remove Question
</button>
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<div key={uuid()}>
<input type="checkbox" />
<input type="text" onChange={this.handleChange} />
</div>
))}
</div>
</li>
);
})}
</ol>