Toggle state taking previous value in react? - javascript

I am trying to create a to-do list app. The basic functionality includes adding and deleting. So when a user selects one or multiple items, a delete button will appear and it will be deleted. My problem is I am implementing a toggle state which when a user clicks on todo item, it will be strikethrough( A strikethrough text decoration will be added via CSS).
The problem arises when I add two items. When I click on the first item , it gets a strike through and when I delete it, the first one goes but the second item gets the strike through this time.
The running sample in codesandbox. Just try adding two items and delete the first one. The second one also gets a strike through.
I believe its because the toggle state value is being remembered.
This is the Content.js component
import "./styles/content.css";
import Individual from "./Individual";
import { useEffect, useState } from "react";
import { updateItem, markIncomplete } from "./action/action";
const Contents = (props) => {
const items = useSelector((state) => state.todoReducer.items);
const dispatch = useDispatch();
const handleClick = (e, isComplete, content, id) => {
// console.log(isComplete);
if (isComplete === false) {
//evaluates false to true
const newobj = {
isComplete: true,
content,
id
};
dispatch(updateItem(newobj));
props.deletebutton(true);
} else {
const falseobj = {
isComplete: false,
content,
id
};
dispatch(markIncomplete(falseobj));
}
};
useEffect(() => {
console.log("statechanging of contents");
});
return (
<div className="content-ui">
<div>
{items.map((vals) => (
<Individual
vals={vals}
deletebutton={props.deletebutton}
handleClick={handleClick}
/>
))}
</div>
</div>
);
};
export default Contents;
This is the individual.js which deals with toggle function
import { useDispatch, useSelector } from "react-redux";
import "./styles/content.css";
import { updateItem, markIncomplete } from "./action/action";
const Individual = (props) => {
console.log("child" + props.vals.isComplete);
const [toggle, isToggled] = useState(false);
const handleToggle = () => {
const mytoggle = !toggle;
isToggled(mytoggle);
};
return (
<div>
<div
className={toggle ? "toggled" : "card-elements"}
onMouseDown={handleToggle}
onClick={(e) => {
props.handleClick(
e,
props.vals.isComplete,
props.vals.content,
props.vals.id
);
handleToggle;
}}
>
{props.vals.content}
</div>
</div>
);
};
export default Individual;
Css of toggler
.toggled {
/* border: 1px solid rgb(94, 94, 94); */
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px;
text-align: left;
box-sizing: border-box;
padding: 10px 3px 10px 7px;
margin-top: 4px;
margin-bottom: 8px;
border-radius: 5px;
background-color: white;
font-size: 12px;
font-family: "Roboto ", monospace;
text-decoration: line-through;
}
.card-elements {
/* border: 1px solid rgb(94, 94, 94); */
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px;
text-align: left;
box-sizing: border-box;
padding: 10px 3px 10px 7px;
margin-top: 4px;
margin-bottom: 8px;
border-radius: 5px;
background-color: white;
font-size: 12px;
font-family: "Roboto ", monospace;
}

You need to add keys to your mapped items (there should also be a warning about this in the console).
Keys help React identify which items have changed, are added, or are removed.
As is stated from React's documents.
return (
<div className="content-ui">
<div>
{items.map((vals) => (
<Individual
key={vals.id} // <-- add unique key
vals={vals}
deletebutton={props.deletebutton}
handleClick={handleClick}
/>
))}
</div>
</div>
);

Related

How can I implement conditional rendering using map function?

I made 5 blocks and want to make the letters on each block thick when the mouse is hover. I made isHover state and changed the thickness of the writing according to the state, but the problem is that the thickness of all five changes. I think I can solve it by using conditional rendering, but I don't know how to use it. Of course, it can be implemented only with css, but I want to implement it with conditional rendering because I am practicing the code concisely.
import "./styles.css";
import styled from "styled-components";
import { useState } from "react";
export default function App() {
const array = [
{ id: "1", title: "ABC" },
{ id: "2", title: "DEF" },
{ id: "3", title: "GHI" },
{ id: "4", title: "JKL" },
{ id: "5", title: "MNO" }
];
const [isHover, setIsHover] = useState(false);
return (
<Head isHover={isHover}>
<div className="header">
{array.map((content, id) => {
return (
<div
className="header__title"
onMouseEnter={() => {
setIsHover(true);
}}
onMouseLeave={() => {
setIsHover(false);
}}
>
{content.title}
</div>
);
})}
</div>
</Head>
);
}
const Head = styled.div`
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
.header {
display: inline-flex;
border: 1px solid black;
box-sizing: border-box;
}
.header__title {
border: 1px solid red;
padding: 5px 10px;
font-weight: ${(props) => (props.isHover ? "700" : "400")};
}
`;
codesandbox
https://codesandbox.io/s/aged-cherry-53pr2r?file=/src/App.js:0-1170
The problem is that you are using the same state for all the 5 blocks. There are multiple approaches you could take to solve this problem.
1. Multiple states
You could create 5 different isHover<N> states (maybe a single one, but as an array)
2. Component extraction
You could just extract out a component for each entry in array and do state management in that component.
function App() {
const array = [...];
return (
<Head>
<div className="header">
{array.map((content, id) => (
<HeaderTitle key={content.id} content={content} />
)}
</div>
</Head>
);
}
function HeaderTitle({ content }) {
const [isHover, setIsHover] = useState(false);
return (
<StyledHeaderTitle
isHover={isHover}
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
>
{content.title}
</StyledHeaderTitle>
);
}
const StyledHeaderTitle = styled.div`
font-weight: ${(props) => (props.isHover ? "700" : "400")};
`
3. Using style prop
Directly apply the font weight using the style prop (An extension to approach 2)
function HeaderTitle({ content }) {
const [isHover, setIsHover] = useState(false);
return (
<StyledHeaderTitle
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
style={{ fontWeight: isHover ? "700" : "400" }}
>
{content.title}
</StyledHeaderTitle>
);
}
4. CSS
CSS already allows you to track hover states over different elements and you don't need to manually track it in javascript.
.header__title {
border: 1px solid red;
padding: 5px 10px;
font-weight: 400;
&:hover {
font-weight: 700;
}
}
There's no need to use React state and event listeners here, you can do it all in CSS instead:
.header__title {
border: 1px solid red;
padding: 5px 10px;
font-weight: 400;
}
.header__title:hover {
font-weight: 700;
}
Just add this pseudo class and you're good to go
.header__title:hover {
font-weight: 700;
}

Will I get the latest state value in this case?

I wanted to know whether my onAdd function in <NewItemButton> will get the latest value of text state.
import { useState } from "react";
import {
NewItemFormContainer,
NewItemInput,
NewItemButton
} from "./styles";
type NewItemFormProps = {
onAdd(text: string): void
}
const NewItemForm = (props: NewItemFormProps) => {
const [text, setText] = useState("");
return (
<NewItemFormContainer>
<NewItemInput
value={text}
onChange={(e) => setText(e.target.value)}
/>
<NewItemButton onClick={() => props.onAdd(text)}>
Create
</NewItemButton>
</NewItemFormContainer>
);
}
export default NewItemForm;
If it does not get the latest value, what other ways can you suggest me? One that comes to my mind to use Refs (forwardRef) and send it directly to the html input element and then call props.onAdd with the current value. But the thing is that I am using styled-components and my NewItemInput looks like this
export const NewItemInput = styled.input`
border-radius: 3px;
border: none;
box-shadow: #091e4240 0px 1px 0px 0px;
margin-bottom: 0.5rem;
padding: 0.5rem 1rem;
width: 100%;
background: #484747;
color: #f1f1f1;
`
So how will do that?

Passing Props in SolidJS

I came across something weird while trying to pass props in SolidJS. I've created a store using createStore which I pass through the component tree using Context.Provider. I also have the helper function useStore which lets me access the store anywhere in the component tree (I'm experimenting with React design patterns in SolidJS). I have two components Anime.jsx (parent) and EpisodeList.jsx (child). I'm fetching data when the Anime component mounts and then populate the store with the setter provided by createStore.After which I pass the fetched data to EpisodeList. However, accessing the props of EpisodeList returns an empty proxy (Not sure why, but I think the EpisodeList component isn't re-rendered when store is updated with store.currentAnimeData). I've attached the output below of the console.log statements below.
Any help regarding this would be highly appreciated.
###################################
# Anime.jsx (Parent component)
###################################
const Anime = (props) => {
const [store, setStore] = useStore();
const getAnimeData = async () => {
const currentAnimeId = store.currentAnime.animeId;
const currentAnimeData = await firebase.getAnimeData(currentAnimeId);
setStore(
produce((store) => {
store.currentAnimeData = currentAnimeData;
})
);
};
onMount(() => {
getAnimeData();
});
return (
<>
<div
className={css`
width: 100%;
min-height: 20px;
margin: 8px 0px 5px 0px;
padding: 0px 10px;
box-sizing: border-box;
font-size: 20px;
word-wrap: break-word;
line-height: 1;
`}
>
<span
className={css`
font-size: 20px;
color: #e32451;
`}
>
{"Watching: "}
</span>
{store.currentAnime.name}
</div>
<Search></Search>
<EpisodeList animeData={store.currentAnimeData.episodes} />
</>
);
};
#####################################
# EpisodeList.jsx (child component)
#####################################
const EpisodeList = (props) => {
console.log(props);
console.log(props.animeData);
...... # UI stuff
return (
<div
className={css`
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
padding-bottom: 5px;
margin-top: 10px;
`}
>
<ScrollActionUp onmousedown={[scroll, true]} onmouseup={onmouseup}>
➭
</ScrollActionUp>
<div
className={css`
width: 100%;
height: 432px;
box-sizing: border-box;
padding: 10px 10px 0px 10px;
overflow: hidden;
`}
ref={scrollRef}
>
<For each={animeData.episodes}>
{(episode, index) => {
return (
<Episode status={episode.watched} episode={episode}></Episode>
);
}}
</For>
</div>
<ScrollActionDown onmousedown={[scroll, false]} onmouseup={onmouseup}>
➭
</ScrollActionDown>
</div>
);
};
###############
# store.jsx
###############
import { createContext, createSignal, useContext } from "solid-js";
import { createStore } from "solid-js/store";
const StoreContext = createContext();
export function ContextProvider(props) {
const [store, setStore] = createStore({});
return (
<StoreContext.Provider value={[store, setStore]}>
{props.children}
</StoreContext.Provider>
);
}
export function useStore() {
return useContext(StoreContext);
}

Preventing refresh page on submit in React

I'm trying to create an editable table that will turn a specific cell in to an <input> once it's clicked and then will run the handleSubmit() method once the user presses return.
Below is an example of a <td> cell using an onClick event to run handleClick() method and turn it's <td></td> in to <form><input></input></form>.
<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>
handleClick(e:React.MouseEvent<HTMLTableDataCellElement, MouseEvent>) {
if(this.state.editing == false){
let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`
e.currentTarget.innerHTML = form;
}
this.setState({editing: true})
}
handleSubmit(e){
e.preventDefault()
}
Using e.preventDefault() does not seem to work in this instance. Every time i press return after changing the text, the page refreshes. How do i stop the page from refreshing in this instance?
I'm guessing you're wanting to achieve something where you can editing columns, modify or abandon changes, and then update things as needed.
This example is with local state, but you could still do it with fetching data.
Click the "Run code snippet" below to see a working example.
// main.js
const { useState } = React;
const App = () => {
// State
const [data, setData] = useState([{ id: 1, name: 'John', editing: false }, { id: 2, name: 'Kevin', editing: false }]);
// Functions
const onSubmitForm = index => event => {
// To prevent form submission
event.preventDefault();
// To prevent td onClick
event.stopPropagation();
const newData = [...data];
newData[index].name = newData[index].temp;
newData[index].editing = false;
delete newData[index].temp;
setData(newData);
}
const onClickToggleEditing = index => event => {
// To prevent td onClick and button conflicting with each other for toggling back on
event.stopPropagation();
const newData = [...data];
newData[index].editing = !newData[index].editing;
newData[index].temp = newData[index].name;
setData(newData);
}
const onInputChange = index => event => {
const newData = [...data];
newData[index].temp = event.target.value;
setData(newData);
}
// Render
// This basically like having its own component
const editing = ( data, index, onChange, onSubmit, onCancel) => {
const onKeyUp = index => event => {
if (event.key === 'Escape') {
onCancel(index)(event);
}
}
return <form onSubmit={onSubmit(index)}><input onKeyUp={onKeyUp(index)} onClick={e => e.stopPropagation()} type="text" value={data.temp} placeholder="Enter text" onChange={onChange(index)} /><button onClick={onSubmit(index)} type="submit">Save</button><button type="button" onClick={onCancel(index)}>Cancel</button></form>
}
return <main>
<h1>Table Editing</h1>
<p><small>Click to edit cell for <b>Name</b>.</small></p>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
{data && data.length > 0 && <tbody>
{data.map((i, k) => <tr key={`row-${k}`}>
<td>{i.id}</td>
<td className="editable" onClick={onClickToggleEditing(k)}>{i.editing ? editing(i, k, onInputChange, onSubmitForm, onClickToggleEditing) : i.name}</td>
</tr>)}
</tbody>}
</table>
<hr />
<p><b>Data Manipulation:</b></p>
<pre><code>{JSON.stringify(data, null, '\t')}</code></pre>
</main>
}
ReactDOM.render(<App />, document.querySelector('#root'));
body {
padding: 0;
margin: 0;
font-family: Arial,sans-serif;
}
main {
padding: 0 20px;
}
h1 {
font-size: 18px;
}
table {
width: 100%;
border-spacing: 0;
}
table tr td,
table tr th {
border: 1px solid #efefef;
height: 30px;
line-height: 30px;
text-align: left;
padding: 6px;
}
table tr th:first-child {
width: 100px;
}
.editable:hover {
background: #efefef;
cursor: pointer;
}
table input {
height: 30px;
line-height: 30px;
font-size: 14px;
padding: 0 6px;
margin-right: 6px;
}
table button {
height: 32px;
border: none;
background: red;
color: white;
font-size: 14px;
padding: 0 10px;
border-radius: 4px;
margin-right: 5px;
cursor: pointer;
}
table button[type=submit] {
height: 32px;
border: none;
background: green;
color: white;
font-size: 14px;
padding: 0 10px;
border-radius: 4px;
}
hr {
border: none;
height: 1px;
background: #999;
margin: 20px 0;
}
pre {
background: #efefef;
padding: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
There are a few issues in your code. I'd better fix them, rather than trying to fix the issue with the form submission. And once it is done, you won't have to fix the issue with the form - there simply won't be any.
First, let's take a look into your editable cell:
<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>
This element should be rendered differently, based on some state. We can achieve this easily with React:
// JSX snippet
<td onClick={ e => this.handleClick(e)}
style={{padding:'5px'}}
key={cellID} id={cellID}>
{this.state.editing ? <Input ... /> : <Label ... />}
</td>
I do not provide all the code, because I believe the components are self-explainable (and you are welcome to name them as you'd like to, I give them very simple names to make their aim clear).
<Input /> encapsulates everything related to editing logic
<Label /> simply renders a text or whatever you need (probably frame.rows[i][idx])
... means that they will most probably have some values/handlers passed as props
In your code, you have this:
let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`
I believe it deserves to be a separate component with its own state and logic (e.g. submit). In fact, this is what <Input ... /> is in my example. And if you make it as a separate component - the following code will work (because it will be a part of that separate component):
handleSubmit(e) {
e.preventDefault()
}
Finally, avoid doing something like that:
e.currentTarget.innerHTML = form;
Reconsider your approach and you simply won't need to do something like that.
hi you can use it like below:
1- i assume you have a return button like below so you can submit in return not using form submit event:
_handleReturn(){
let val = document.getElementById("your input id");
//you can post above text to server if you want
//Do Somthing
}
<button id="btn_return" onClick={this._handleReturn} />
2- i don't see where you trigger handleSubmit, but submitting form cause refresh, you should use ajax if you don't want.

multi step form arrange display

I have created a multi-step form to be able to create a smooth and easy onboarding.
I am not able to properly display the button and the input/label.
I am looking to get the label and input align left and the button previous and next displayed on the same line but one of the left and one on the right. Also my I reach the latest form, the 'next' button is no more displayed and I show a submit.
The code works, it's just the display arrangement which not good.
This how it looks:
and I am more looking for something like this:
Only the back and Next are not properly dispayed on this image, it should be closer to the input.
Otherwise, it's exactly what I am looking
Label then input (always below the label), and then the buttons below the input and label.
Here is the code:
MasterForm:
import React from 'react';
import ClassCreationFormStep1 from './ClassCreationFormStep1'
import ClassCreationFormStep2 from './ClassCreationFormStep2'
import ClassCreationFormStep3 from './ClassCreationFormStep3'
import ClassCreationFormStep4 from './ClassCreationFormStep4'
import ClassCreationFormStep5 from './ClassCreationFormStep5'
import ClassCreationFormStep6 from './ClassCreationFormStep6'
import ClassCreationFormStep7 from './ClassCreationFormStep7'
import ClassCreationFormStep8 from './ClassCreationFormStep8'
import ClassCreationFormStep9 from './ClassCreationFormStep9'
import ClassCreationFormStep10 from './ClassCreationFormStep10'
import ClassCreationFormStep11 from './ClassCreationFormStep11'
import ClassCreationFormStep12 from './ClassCreationFormStep12'
import ClassCreationFormStep13 from './ClassCreationFormStep13'
import './CreateClassOnBoardingForm.css';
class CreateClassOnBoardingForm extends React.Component {
constructor(props) {
super(props)
// Set the initial input values
this.state = {
currentStep: 1, // Default is Step 1
classTeacherName: '',
classProfilePic: '',
classEmail: '',
className: '',
classAttendeesWillLearn: '',
classMaxClass: '',
classWhatToBring: '',
classWillBe: '',
classLocation: '',
classCost: '',
typeOfClass: '',
classExtra: '',
classPics: '',
}
// Bind the submission to handleChange()
this.handleChange = this.handleChange.bind(this)
this._next = this._next.bind(this)
this._prev = this._prev.bind(this)
}
_next() {
let currentStep = this.state.currentStep
// If the current step is 1 or 2, then add one on "next" button click
currentStep = currentStep >= 12? 13: currentStep + 1
this.setState({
currentStep: currentStep
})
}
_prev() {
let currentStep = this.state.currentStep
// If the current step is 2 or 3, then subtract one on "previous" button click
currentStep = currentStep <= 1? 1: currentStep - 1
this.setState({
currentStep: currentStep
})
}
// Use the submitted data to set the state
handleChange(event) {
const {name, value} = event.target
this.setState({
[name]: value
})
}
// Trigger an alert on form submission
handleSubmit = (event) => {
event.preventDefault()
const { classTeacherName, classProfilePic, classEmail,
className, classAttendeesWillLearn,classMaxClass, classWhatToBring,
classWillBe, classLocation, classCost, typeOfClass, classExtra, classPics } = this.state
alert(`Your registration detail: \n
classTeacherName: ${classTeacherName} \n
classProfilePic: ${classProfilePic} \n
classEmail: ${classEmail} \n
className: ${className} \n
classAttendeesWillLearn: ${classAttendeesWillLearn} \n
classMaxClass: ${classMaxClass} \n
classWhatToBring: ${classWhatToBring} \n
classWillBe: ${classWillBe} \n
classLocation: ${classLocation} \n
classCost: ${classCost} \n
typeOfClass: ${typeOfClass} \n
classExtra: ${classExtra} \n
classPics: ${classPics} \n
`)
window.open("/successfull", "_self") //to open new page
}
get previousButton(){
let currentStep = this.state.currentStep;
// If the current step is not 1, then render the "previous" button
if(currentStep !==1){
return (
<button
className="blue-button"
type="button" onClick={this._prev}>
Previous
</button>
)
}
// ...else return nothing
return null;
}
get nextButton(){
let currentStep = this.state.currentStep;
if(currentStep <13){
return (
<button
className="blue-button"
type="button" onClick={this._next}>
Next
</button>
)
}
// ...else render nothing
return null;
}
render() {
return (
<React.Fragment>
<p>Step {this.state.currentStep} </p>
<form onSubmit={this.handleSubmit}>
<ClassCreationFormStep1
currentStep={this.state.currentStep}
handleChange={this.handleChange}
classTeacherName={this.state.classTeacherName}
/>
<ClassCreationFormStep2
currentStep={this.state.currentStep}
handleChange={this.handleChange}
classProfilePic={this.state.classProfilePic}
/>
....
<ClassCreationFormStep13
currentStep={this.state.currentStep}
handleChange={this.handleChange}
classPics={this.state.classPics}
/>
{this.previousButton}
{this.nextButton}
</form>
</React.Fragment>
)
}
}
export default CreateClassOnBoardingForm;
The Css below is used on the master and child
.blue-button {
border-radius: 21px;
background-color: #14cff0;
border-color: #14cff0;
font-family: Source Sans Pro;
font-size: 13px;
font-weight: bold;
text-align: center;
color: #ffffffff;
box-shadow: 0px 8px 18px 0 rgba(0,0,0,0.14);
padding-top: 5px;
padding-bottom: 7px;
padding-left: 20px;
padding-right: 20px;
}
.label-txt {
font-family: Source Sans Pro;
font-size: 30px;
font-weight: bold;
font-stretch: normal;
font-style: normal;
line-height: 0.77;
letter-spacing: -0.6px;
text-align: left;
color: #333333;
}
.form-control-village {
font-family: Source Sans Pro;
font-size: 16px;
line-height: 1.6;
text-align: left;
color: #616161;
padding: 0px 0px 0px 0px;
margin: 0px 0px 0px 0px;
background-color: #ffffff;
border-bottom: 3px solid #ff7255;
border-top: 0px none;
border-left: 0px none;
border-right: 0px none;
}
and here is the child form:
1st one:
import React from 'react';
import TextContents from '../../assets/translations/TextContents'
import './CreateClassOnBoardingForm.css';
class ClassCreationFormStep1 extends React.Component {
render() {
if (this.props.currentStep !== 1) { // Prop: The current step
return null
}
return(
<div className="form-group">
<label className="label-txt" htmlFor="classTeacherName">{TextContents.FormClassTeacherName}</label>
<input
className="form-control-village"
id="classTeacherName"
name="classTeacherName"
type="text"
placeholder=""
value={this.props.classTeacherName} // Prop: The email input data
onChange={this.props.handleChange} // Prop: Puts data into state
/>
</div>
)
}
}
export default ClassCreationFormStep1
second one:
import React from 'react';
import TextContents from '../../assets/translations/TextContents'
import './CreateClassOnBoardingForm.css';
class ClassCreationFormStep2 extends React.Component {
render() {
if (this.props.currentStep !== 2) { // Prop: The current step
return null
}
return(
<div className="form-group">
<label className="label-txt" htmlFor="classProfilePic">{TextContents.FormClassProfilePic}</label>
<input
className="form-control-village"
id="classProfilePic"
name="classProfilePic"
type="file"
value={this.props.classProfilePic} // Prop: The email input data
onChange={this.props.handleChange} // Prop: Puts data into state
/>
</div>
)
}
}
export default ClassCreationFormStep2
and the latest one, when submit shows up
import React from 'react';
import TextContents from '../../assets/translations/TextContents'
import './CreateClassOnBoardingForm.css';
class ClassCreationFormStep13 extends React.Component {
render() {
if (this.props.currentStep !== 13) { // Prop: The current step
return null
}
return(
<React.Fragment>
<div className="form-group">
<label className="label-txt" htmlFor="classPics">{TextContents.FormClassPics}</label>
<input
className="form-control-village"
id="classPics"
name="classPics"
type="file"
multiple
value={this.props.classPics} // Prop: The email input data
onChange={this.props.handleChange} // Prop: Puts data into state
/>
</div>
<button
className="blue-button"
type="submit">
{TextContents.SubmitBtn}
</button>
</React.Fragment>
)
}
}
export default ClassCreationFormStep13
Any idea how to make it nice like the latest image I have posted
=====
I am looking to have something like this:
if you want them positioned to the bottom left and right you need to set a height and position: relative
<div className="container>
<button className="backButton>Back</button>
<button className="nextButton>Next</button>
</div>
.container {
height: 200px; // example
width: 200px;
position: relative;
}
.backButton {
position: absolute;
bottom: 0;
left: 0;
}
.nextButton {
position: absolute;
bottom: 0;
right: 0;
}

Categories

Resources