how to create a file tree explorer/view using react js? - reactjs

I have an react js application whose landing page(index page) allows the user to create a new folder or new view.
As seen in the screenshot the folders and views are displayed in the tile view format.I would like to change the view to a tree structure similar to the file explorer seen on ide such as visual studio code or eclipse.
My render function for the landing page-
render() {
const formList = localStorage.getItem("FormList") !== null ? JSON.parse(localStorage.getItem("FormList")) : [];
const { openmodal, newfolder, foldername, folderList, formView, alertMessage, alert } = this.state;
const folderid = this.props.history.location.pathname;
let fid = folderid.replace('/folder/', '');
return (
<div className="bacgrounImage">
<AlertFunction type={alert} msg={alertMessage} />
<Container fluid>
<Row>
<Col lg="12"
className="spilt folderheader"
>
<div style={{ paddingTop: '7px', paddingLeft: '3%' }}>
<NavLink to={fid === '/' ? "/formcreate" : '/formcreate/' + fid} >
<button className='butt' onClick={() => {
localStorage.setItem('viewId', null);
}} style={{ float: 'right', width: '14%', height: '43px', marginLeft: '10px' }} onClick={e => this.layoutset(e, null, null)}>
<h6 style={{ fontWeight: '500' }}>Create New View</h6>
</button>
</NavLink>
{newfolder === null &&
<button className='butt' type='button' onClick={this.folderName} style={{ width: '15%%', float: 'right' }} >
<img src={require('./image/newFolder.svg')} />
<span style={{ fontWeight: '500' }}>Create New Folder</span></button>
}
</div>
<div>
<h4>File List</h4>
</div>
</Col>
<Col lg='12' className='newfolder folderList'>
<div style={{ display: newfolder === 2 ? 'block' : 'none', padding: '8px 8px 16px 1px' }}>
<span style={{ padding: '6px 18px', cursor: 'pointer' }} onClick={e => this.backToForm(e)}><i className="fa fa-arrow-left" aria-hidden="true" ></i></span>
</div>
{(folderList !== undefined && folderList.length > 0) &&
folderList.map((val, i) => {
return <div key={i + "create"} className='list' id={val.id} onDoubleClick={() => this.folderClick(val.id, 1)}>
<img src={require('./image/folder.svg')} style={{ width: '48px' }} />
<span>{val.name}</span>
</div>
}
)
}
{(formView !== undefined && formView.length > 0) &&
formView.map((val, i) =>
<div key={i + "create"} className='list' id={val.id} onDoubleClick={() => this.folderClick(val.id, 2)}>
<img src={require('./image/file.svg')} style={{ width: '48px' }} />
<span>{val.name}</span>
</div>)
}
{
(folderList !== undefined && folderList.length === 0 && formView !== undefined && formView.length === 0) &&
<div className='noDataFound'>No data found </div>
}
{newfolder === 1 &&
<div className='list' style={{ backgroundColor: '#d3daff' }}>
<img src={require('./image/folder.svg')} style={{ width: '48px' }} />
<input value={foldername} onChange={e => this.setState({ foldername: e.target.value })} onKeyPress={this.createnewFolder} type='text' style={{ width: '72%', marginLeft: '2px', height: '27px' }} onFocus={this.handleFocus} />
</div>
}
</Col>
<div lg="12">
<Formlisting formList={formList} openmodal={openmodal} toggle={this.toggle} />
</div>
</Row>
</Container>
</div>
);
}
How do i modify the render function to change the view from the tile view to tree structure view as seen in the screenshot.Plz help?

Related

the drag and drop feature doesnt work like it supposed to

I havent used react this deeply before and i am onfused on what to be done i am not able to figure out why the drag and drop feature is not working as it should please help , i was doing a follow along tutorial and this is exactly what he did and was able to drag and drop the slides and i have checked the entire code and wasnt able to fighure out what was it that i was doing wrong please help
import React, { useState, useEffect } from "react";
import CropOriginalIcon from "#material-ui/icons/CropOriginal";
import Select from "#material-ui/core/Select";
import Switch from "#material-ui/core/Switch";
import CheckBoxIcon from "#material-ui/icons/CheckBox";
import ShortTextIcon from "#material-ui/icons/ShortText";
import SubjectIcon from "#material-ui/icons/Subject";
import MoreVertIcon from "#material-ui/icons/MoreVert";
import { BsTrash } from "react-icons/bs";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import DragIndicatorIcon from "#material-ui/icons/DragIndicator";
import { Icon, IconButton, MenuItem, Typography } from "#material-ui/core";
import FilterNoneIcon from "#material-ui/icons/FilterNone";
import AddCircleOutlineIcon from "#material-ui/icons/AddCircleOutline";
import OndemandVideoIcon from "#material-ui/icons/OndemandVideo";
import TextFieldsIcon from "#material-ui/icons/TextFields";
import { BsFileText } from "react-icons/bs";
import Accordion from "#material-ui/core/Accordion";
import AccordionSummary from "#material-ui/core/AccordionSummary";
import AccordionDetails from "#material-ui/core/AccordionDetails";
import Button from "#material-ui/core/Button";
import { FcRightUp } from "react-icons/fc";
import Closelcon from "#material-ui/icons/Close";
import Radio from "#material-ui/core/Radio";
import FormControlLabel from "#material-ui/core/FormControlLabel";
import "./Question_form.css";
function Question_form() {
const [questions, setQuestions] = useState([
{
questionText: "Which is the capital city of Karnataka??",
questionType: "radio",
options: [
{ optionText: "Bengaluru" },
{ optionText: "Mandya" },
{ optionText: "Hubli" },
{ optionText: "Mandya" },
],
open: true,
required: false,
},
]);
function changeQuestion(text, i) {
var newQuestion = [...questions];
newQuestion[i].questionText = text;
setQuestions(newQuestion);
console.log(newQuestion);
}
function changeOptionValue(text, i, j) {
var optionsQuestion = [...questions];
optionsQuestion[i].options[j].optionText = text;
setQuestions(optionsQuestion);
console.log(optionsQuestion);
}
function addQuestionType(i, type) {
let qs = [...questions];
console.log(type);
qs[i].questionType = type;
setQuestions(qs);
}
function removeOption(i, j) {
var RemoveOptionQuestion = [...questions];
if (RemoveOptionQuestion[i].options.length > 1) {
RemoveOptionQuestion[i].options.splice(j, 1);
setQuestions(RemoveOptionQuestion);
console.log(i + "_" + j);
}
}
function addOption(i) {
var optionsOfQuestion = [...questions];
if (optionsOfQuestion[i].options.length < 5) {
optionsOfQuestion[i].options.push({
optionText: "option " + (optionsOfQuestion[i].options.length + 1),
});
} else {
console.log("Max 5 options");
}
setQuestions(optionsOfQuestion);
}
function copyQuestion(i) {
let qs = [...questions];
var newQuestion = qs[i];
setQuestions([...questions, newQuestion]);
}
function deleteQuestion(i) {
let qs = [...questions];
if (questions.length > 1) {
qs.splice(i, 1);
}
setQuestions(qs);
}
function requiredQuestion(i) {
var reqQuestion = [...questions];
reqQuestion[i].required = !reqQuestion[i].required;
console.log(reqQuestion[i].required + " " + i);
setQuestions(reqQuestion);
}
function addMoreQuestionField() {
setQuestions([
...questions,
{
questionText: "Question",
questionType: "radio",
options: [{ optionText: "Option 1" }],
open: true,
required: false,
},
]);
}
function onDragEnd(result) {
if (!result.destination) {
return;
}
var itemgg = [...questions];
const itemF = reorder(
itemgg,
result.source.index,
result.destination.index
);
setQuestions(itemF);
}
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
function questionsUI() {
return questions.map((ques, i) => (
<Draggable key={i} draggableId={i + "id"} index={i}>
{(provided,snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<div>
<div style={{ marginBottom: "0px" }}>
<div style={{ marginBottom: "0px", width: "100%" }}>
<DragIndicatorIcon
style={{
transform: "rotate(-90deg)",
color: "#DAE0E2",
position: "relative",
left: "300px",
}}
fontSize="small"
/>
</div>
<div>
<Accordion
className={questions[i].open ? "add border" : ""}
expanded={questions[i].open}
>
<AccordionSummary
aria-controls="panel1a-content"
id="panel1a-header"
elevation={1}
style={{ width: "100%" }}
>
{/* {questions[i].open ? (
<div className="saved_questions">
<Typography
style={{
fontSize: "15px",
fontWeight: "400",
letterSpacing: ".1px",
lineHeight: "24px",
paddingBottom: "8px"
}}
>
{i + 1}.{questions[i].questionText}
</Typography>
{ques.options.map((op, j) => (
<div key={j}>
<div style={{ display: "flex" ,}}>
<FormControlLabel
style={{ marginLeft: "5px", marginBottom: "5px" }}
disabled
control={
<input
type={ques.questionType}
color="primary"
style={{ marginRight: "3px" }}
required={ques.type}
/>
}
label={
<Typography
style={{
fontFamily: "Roboto,Arial,sans-serif",
fontSize: "13px",
fontWeight: "400",
letterSpacing: ".2px",
lineHeight: "20px",
color: "#202124",
}}
>
{ques.options[j].optionText}
</Typography>
}
/>
</div>
</div>
))}
</div>
) :
""
} */}
</AccordionSummary>
<div className="question_boxes">
<AccordionDetails className="add_question">
<div className="add_question_top">
<input
type="text "
className="question"
placeholder="Question"
value={ques.questionText}
onChange={(e) => {
changeQuestion(e.target.value, i);
}}
></input>
<CropOriginalIcon style={{ color: "#5f6368" }} />
<Select
className="select"
style={{ color: "#5f6368", fontSize: "13px" }}
>
<MenuItem
id="text"
value="Text"
onClick={() => {
addQuestionType(i, "text");
}}
>
<SubjectIcon style={{ marginRight: "10px" }} />
Paragraph
</MenuItem>
<MenuItem
id="checkbox"
value="Checkbox"
onClick={() => {
addQuestionType(i, "checkbox");
}}
>
<CheckBoxIcon
style={{
marginRight: "10px",
color: "#70757a",
}}
checked
/>
CheckBoxes
</MenuItem>
<MenuItem
id="radio"
value="Radio"
onClick={() => {
addQuestionType(i, "radio");
}}
>
<Radio
style={{
marginRight: "10px",
color: "#70757a",
}}
checked
/>
Multiple Choice
</MenuItem>
</Select>
</div>
{ques.options.map((op, j) => (
<div className="add_question_body" key={j}>
{ques.questionType !== "text" ? (
<input
type={ques.questionType}
style={{ marginRight: "10px" }}
/>
) : (
<ShortTextIcon style={{ marginRight: "10px" }} />
)}
<div>
<input
type="text"
className="text_input"
placeholder="option"
value={ques.options[j].optionText}
onChange={(e) => {
changeOptionValue(e.target.value, i, j);
}}
></input>
</div>
<CropOriginalIcon style={{ color: "#5f6368" }} />
<IconButton aria-label="delete">
<Closelcon
onClick={() => {
removeOption(i, j);
}}
/>
</IconButton>
</div>
))}
{ques.options.length < 5 ? (
<div className="add_question_body">
<FormControlLabel
disabled
control={
ques.questionText !== "text" ? (
<input
type={ques.questionType}
color="primary"
inputProps={{
"aria-label": "secondary checkbox",
}}
style={{
marginLeft: "10px",
marginRight: "10px",
}}
disabled
/>
) : (
<ShortTextIcon
style={{ marginRight: "10px" }}
/>
)
}
label={
<div>
<input
type="text"
className="text_input "
style={{ fontSize: "13px", width: "60px" }}
placeholder="Add other"
></input>
<Button
size="small"
onClick={() => {
addOption(i);
}}
style={{
textTransform: "none",
color: "#4285f4",
fontSize: "13px",
fontWeight: "600",
}}
>
Add options
</Button>
</div>
}
/>
</div>
) : (
""
)}
<div className="add_footer">
<div className="add_question_bottom_left">
<Button
size="small"
style={{
textTransform: "none",
color: "4285f4",
fontSize: "13px",
fontWeight: "600",
}}
>
<FcRightUp
style={{
border: "2px solid #4285f4",
padding: "2px",
marginRight: "8px",
}}
/>
Answer Key
</Button>
</div>
<div className="add_question_bottom">
<IconButton
aria-label="Copy"
onClick={() => {
copyQuestion(i);
}}
>
<FilterNoneIcon />
</IconButton>
<IconButton
aria-label="delete"
onClick={() => {
deleteQuestion(i);
}}
>
<BsTrash />
</IconButton>
<span
style={{ color: "#5f6368", fontSize: "13px" }}
>
required
</span>
<Switch
name="checkedA"
color="primary"
onClick={() => {
requiredQuestion(i);
}}
value={ques.type}
/>
<IconButton>
<MoreVertIcon />
</IconButton>
</div>
</div>
</AccordionDetails>
<div className="question_edit">
<AddCircleOutlineIcon
onClick={addMoreQuestionField}
className="edit"
/>
<OndemandVideoIcon className="edit" />
<CropOriginalIcon className="edit" />
<TextFieldsIcon className="edit" />
</div>
</div>
</Accordion>
</div>
</div>
</div>
</div>
)}
</Draggable>
));
}
return (
<div>
<div className="question_form">
<br></br>
<div className="section">
<div className="question_title_section">
<div className="question_form_top">
<input
type="text"
className="question_form_top_name"
style={{ color: "black" }}
placeholder="Untitled Document"
></input>
<input
type="text"
className="question_form_top_desc"
placeholder="Form description"
></input>
</div>
</div>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div
className="droppable"
{...provided.droppableProps}
ref={provided.innerRef}
>
{questionsUI()}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
</div>
</div>
)
}
export default Question_form;
/*here i am not able to drag and drop the element please help */

How to close only one Div at a time in React?

Code:-
const [Close, setClose] = useState(true)
<div className="allDivs">
{item.map((item, index) => {
// console.log("myDivs", myDivs);
return (
<Fragment key={index} >
<div className="tableHeaderBody" id="CLOSEDIV" style={{display: Close ? 'initial' : 'none'}}>
<div className="TableText">
<div className="TableTextHide"></div> <div style={{ color: "white" }} id="SHOW">{item.val}</div></div>
<div className="CloseIcon" id="CloseBtn"><FaCircle style={{ color: "#FC0000", width: "10px", height: "10px", alignItems: "right" }} onClick={() => setClose(false)} /></div>
</div>
</Fragment>
)
})
}
</div>
I want that when i click the Red circle at any div (show in image) it close the div, but right now when i click the One div red circle its closes all the div
please help.
Try this:
Create a new component ChildComponent:
export default function ChildComponent({item}) {
const [Close, setClose] = useState(true) // Every Child now has it's own setClose controll
return (
<Fragment>
<div className="tableHeaderBody" id="CLOSEDIV" style={{display: Close ? 'initial' : 'none'}}>
<div className="TableText">
<div className="TableTextHide"></div>
<div style={{ color: "white" }} id="SHOW">{item.val}</div>
</div>
<div className="CloseIcon" id="CloseBtn">
<FaCircle style={{ color: "#FC0000", width: "10px", height: "10px", alignItems: "right" }} onClick={() => setClose(false)} />
</div>
</div>
</Fragment>
)
}
Pass the ChildComponent to your component shown above:
<div className="allDivs">
{item.map((item, index) => (
<div key={index}>
<ChildComponent item={item} />
</div>
))}
</div>

How to update height prop with useRef in React?

I need to dynamically define the size of HTML element and set its height to component. I tried to do this with useRef but it doesn't work as expected because of state which contains the previous value (not the current one). Could someone help me with this?
And here's the link: CodeSandBox https://codesandbox.io/s/happy-water-fzqk8?file=/src/App.js
The below code works fine but there's hardcored variable HEIGHT which defines the height of a tab. My task is to make the height dynamic
import { useState } from 'react';
const HEIGHT = {
0: 200,
1: 400,
2: 800,
}
function App() {
const [tab, setTab] = useState(0);
const switchTab = (id) => {
setTab(id);
};
return (
<div
style={{
margin: '100px auto',
backgroundColor: 'pink',
width: '400px',
overflow: 'hidden',
height: HEIGHT[tab], // need this to be dynamic not hardcored
}}
>
<div>
{tab === 0 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 1</h2>
<input />
<button onClick={() => switchTab(1)}>Go to tab 2</button>
<p>Some text here</p>
</div>
)}
{tab === 1 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 2</h2>
<input />
<button onClick={() => switchTab(0)}>Go to tab 1</button>
<button onClick={() => switchTab(2)}>Go to tab 3</button>
<p>
Some more text here. Some more text here. Some more text here. Some more text here.
Some more text here. Some more text here. Some more text here
</p>
</div>
)}
{tab === 2 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 3</h2>
<input />
<button onClick={() => switchTab(0)}>Go to tab 1</button>
<button onClick={() => switchTab(1)}>Go to tab 2</button>
</div>
)}
</div>
</div>
);
}
What I tried:
Added useRef and state which holds the element height
const elRef = useRef(0);
const [height, setHeight] = useState(elRef.current.offsetHeight);
Added function which calculates the size of an element and then sets it to state variable
const resizeHeight = useCallback(() => {
const size = elRef.current.offsetHeight;
setHeight(size)
}, [elRef]);
Added state Height to styles this way
<div
style={{
margin: '100px auto',
backgroundColor: 'pink',
width: '400px',
overflow: 'hidden',
height: height, // it should be the element size
}}
>
It doesn't work((
Here's the link...with the state height - undefined
https://codesandbox.io/s/objective-brown-zq7ih?file=/src/App.js
You can easily update your elRef reference in the switchTab handler without using useEffect and any useCallback hooks:
const elRef = useRef(0);
const SwitchTab = (id) => {
setTab(id);
setHeight(elRef.current.offsetHeight)
};
Now pass the elRef to the ref property of your target div:
return (
<div
style={{
margin: '100px auto',
backgroundColor: 'pink',
width: '400px',
overflow: 'hidden',
height: HEIGHT[tab],
}}
>
<div ref={elRef}> // ------------------------> added here
{tab === 0 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 1</h2>
<input />
<button onClick={() => switchTab(1)}>Go to tab 2</button>
<p>Some text here</p>
</div>
)}
{tab === 1 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 2</h2>
<input />
<button onClick={() => switchTab(0)}>Go to tab 1</button>
<button onClick={() => switchTab(2)}>Go to tab 3</button>
<p>
Some more text here. Some more text here. Some more text here. Some more text here.
Some more text here. Some more text here. Some more text here
</p>
</div>
)}
{tab === 2 && (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h2>Tab 3</h2>
<input />
<button onClick={() => switchTab(0)}>Go to tab 1</button>
<button onClick={() => switchTab(1)}>Go to tab 2</button>
</div>
)}
</div>
</div>
);

Button/dropdown button disabled by default without specifying disabled

I am trying to add a dropdown button in my react project and its rendering as disabled by default. why is this happening ?
The first dropdown is working fine, i called the same dropdown in the navbar after this one and it renders as disabled. I tried other things as well, like adding a button also would not work for me.
The navbar is diplayed when i get a response from the backend and a different component is rendered (ResultTable)
import React from "react";
import ResultTable from "./ResultTable";
...
import DropdownButton from "react-bootstrap/DropdownButton";
import Dropdown from "react-bootstrap/Dropdown";
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
//more state values
threshold: 0.75
};
this.thresholdChange = this.thresholdChange.bind(this);
}
thresholdChange(input) {
this.setState({
threshold: input
});
}
toProperCase = function (txt) {
return txt.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
};
render() {
const { responseData } = this.state;
return (
<div className="container-flex container-without-scroll wrapper"
style={{
backgroundImage: `url(${bg})`,
width: "100%",
height: "100vh",
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
overFlow:'hidden'
}}
>
<div
className={`container-fluid `}>
{this.state.displayTable ? (
<Navbar
style={{
position: "fixed",
left: "50%",
top: "95%",
transform: "translate(-50%, -90%)",
backgroundColor: 'black'
}}
sticky="bottom"
>
<br />
<Navbar.Collapse className="justify-content-end">
<Button
variant="primary"
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0 &&
this.props.initialTransaction
? true
: false
}
size="sm"
style={{ color: "#FFF" }}
onClick={this.undoAction}
>
<span className=" fa fa-undo "></span>
Undo
</Button>
<Button
variant="primary"
size="sm"
style={{ color: "#FFF" }}
disabled={
(this.props.initialTransaction &&
this.props.initialTransaction.version) <
(this.props.currentVersion &&
this.props.currentVersion.version)
? false
: true
}
onClick={this.redoAction}
>
<span className=" fa fa-repeat "></span>
Redo
</Button>
<Button
variant="success"
size="sm"
style={{ color: "#FFF" }}
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0
? true
: false
}
onClick={() =>
this.exportExcel(this.props.initialTransaction)
}
>
<span className=" fa fa-download "></span>
Export
</Button>
<DropdownButton
size="md"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
key = {Math.random()}
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</Navbar.Collapse>
<br/>
</Navbar>
) : null}
{this.state.displayTable ? null : (
<div
className="col-md-4 col-md-offset-4"
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: 'rgba(14, 13, 13, 0.74)'
}}
>
<br />
<div className="row">
<div className="input-group col-md-9">
<div className="input-group-prepend">
<span
style={{ cursor: 'pointer' }}
onClick={this.onFormSubmit}
className="input-group-text"
id="inputGroupFileAddon01"
>
{" "}
Upload{" "}
</span>
</div>
<div className="custom-file">
<input
type="file"
className="custom-file-input"
id="inputGroupFile01"
onChange={this.onChange}
aria-describedby="inputGroupFileAddon01"
/>
<label
className="custom-file-label"
htmlFor="inputGroupFile01"
>
{this.props.active && this.props.active.filename}
</label>
</div>
</div>
<div className="col-md-3">
<DropdownButton
size="md"
id="dropdown-item-button"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</div>
</div>
<br />
</div>
)}
<div >
{this.state.displayTable ? (
<div className = "container-flex" style =
{{overflowY:'scroll', maxHeight:'80vh'}}>
<ResultTable
data={responseData}
afterMerge={params => {
this.afterMerge(params);
}}
/>
</div>
) : null}
</div>
</div>
</div>
);
}
}
// Maps state from store to props
const mapStateToProps = (state, ownProps) => {
return {
};
};
// Maps actions to props
const mapDispatchToProps = dispatch => {
return {
};
};
// Use connect to put them together
export default connect(
mapStateToProps,
mapDispatchToProps
)(MainContainer);

OnClick passing undefined

I am trying to pass an onClick value, but it passes undefined. Works well if it is not a Card/Paper/Div but I need this "button" to be a Card/paper/div
onClick={() => this.handleChange('bostadstyp')}
onClick={ value='villa', handleChange('bostadstyp')}
render() {
const { bostadstyp } = this.props;
const { auth } = this.props;
const { value, values, handleChange, handleClick } = this.props;
const { backgroundColori } = this.props;
const backgroundColor2 = "#F09515";
const aa = "";
// const imageUrl = window.innerWidth >= "1600px" ? Banner1 : Banner2;
// {if (!auth.uid) return <Redirect to="/loggain" />;}
return (
<div>
<img
className="stars3"
src={Logo}
width="15%"
align="center"
marginBottom="10px"
/>
<img src={Logo} width="15%" align="center" marginBottom="10px" />
<div style={{ backgroundColor: "#F1F1F1", padding: "30px" }}>
<h2
style={{
marginTop: "0px",
marginLeft: "10%",
color: "#F09515",
fontFamily: "Avenir",
fontWeight: "bold"
}}
>
{" "}
Dina Preferenser{" "}
</h2>
</div>
<form
className="background123"
style={{
backgroundColor: "#fdfdfd",
marginTop: "0px",
marginBottom: "0px"
}}
>
<Card
className="row xl12 l12 m12 s12"
style={{
marginLeft: "10%",
marginRight: "10%",
padding: "30px",
backgroundColor: "#fdfdfd"
}}
>
<br />
<div className="col xl6 l6 m12 s12">
<h4
style={{
fontFamily: "Avenir",
fontWeight: "bold",
color: "#F09515"
}}
>
1. Välj din boendestyp
</h4>
<p className="texti" style={{ fontSize: "16px" }}>
Vi behöver den här uppgift då vissa avtal endast gäller för
vissa anläggningstyper.
</p>
</div>
<div className="col xl6 l6 m12 s12">
<Card
className="row cardi xl12 l12 m12 s12"
style={{ width: "270%", backgroundColor: `white` }}
value={"villa"}
onClick={handleChange("bostadstyp")}
>
<div className=" col xl7 l7 m6 s6">
<img src={villa} width="50px" />
</div>
<div className="col xl5 l5 m5 s5">
<h6
className="texti"
style={{ fontSize: 16, textAlign: "right" }}
>
Villa/radhus
</h6>
</div>
</Card>
</div>
</Card>
</form>
</div>
);
}
I expect to 'values.bostadstyp' get the value 'villa'
because you are using function in the class so you must using this.handleChange instead of handleChange
<Card onClick={() => this.handleChange('bostadstyp' )}>
....
</Card>
You need to attach the onClick() listener to a <CardActionsArea/> component which should be nested inside your <Card/> component
Something like
<Card className="row cardi xl12 l12 m12 s12" style={{ width: '270%', backgroundColor: `white` }} value={'villa'} onClick={handleChange('bostadstyp' )} >
<div className=" col xl7 l7 m6 s6">
<img src={villa} width="50px" />
</div>
<div className="col xl5 l5 m5 s5">
<h6 className="texti" style={{ fontSize: 16, textAlign: "right" }}>Villa/radhus</h6>
</div>
</Card>
Also, I suggest looking into the <CardActions/> documentation, the example here shows how its used
Can you try below code in your card element:
<Card className="row cardi xl12 l12 m12 s12"
style={{ width: '270%', backgroundColor: `white` }} value={'villa'}
onClick={(e) => {
e.preventDefault();
this.handleChange('bostadstyp');
}}>
The issue may be due to one of the below reasons:
1. handleChange() not bound with this.
2. To pass values from onClick handler you should use (e) => func('value')
3. The click is happening inside form element, its better to include event.preventDefault()
You need user arrow function:
onClick={() => { this.handleChange('bostadstyp' ) }}
<Card className="row cardi xl12 l12 m12 s12" style={{ width: '270%', backgroundColor: `white` }} value={'villa'} onClick={() => { this.handleChange('bostadstyp' ) }} >
<div className=" col xl7 l7 m6 s6">
<img src={villa} width="50px" />
</div>
<div className="col xl5 l5 m5 s5">
<h6 className="texti" style={{ fontSize: 16, textAlign: "right" }}>Villa/radhus</h6>
</div>
</Card>
UPDATE
Handle Change from parent component:
Make sure your handleChange is bound properly by explicitly binding it or using an arrow function syntax:
this.handleChange = this.handleChange.bind(this) // In component's constructor
// or
handleChange = (value, input) => {
this.setState({
[input]: value
});
};
onClick expects a function to invoke, so you need to wrap your handler into one:
<Card onClick={() => handleChange('villa', 'bostadstyp')}></Card>

Resources