How to call a modal from an onClick event - reactjs

Trying to trigger a modal popup from an onClick event as below:
import {KTSVG} from '../../../../../../../_metronic/helpers'
import {useListView} from '../../core/ListViewProvider'
import { CreateAppModal } from '../../manage-properties-modal/add-property-modal/AddPropertyModal'
// import {UsersListFilter} from './UsersListFilter'
const PropertyListToolbar = () => {
const {setItemIdForUpdate} = useListView()
const openAddUserModal = () => {
setItemIdForUpdate(null)
}
return (
<div className='d-flex justify-content-end' data-kt-user-table-toolbar='base'>
{/* <UsersListFilter /> */}
{/* begin::Export */}
{/* <button type='button' className='btn btn-light-primary me-3' onClick={openAddUserModal}>
<KTSVG path='/media/icons/duotune/arrows/arr078.svg' className='svg-icon-2' />
Export Details
</button> */}
{/* end::Export */}
{/* begin::Add user */}
<button type='button' className='btn btn-primary' onClick={CreateAppModal}>
<KTSVG path='/media/icons/duotune/arrows/arr075.svg' className='svg-icon-2' />
New Property
</button>
{/* end::Add user */}
</div>
)
}
export {PropertyListToolbar}
The setItemIdForUpdate code, I would like to just disable for now and just get the button to launch the below modal, which I can then customize before I look at saving its state.
import {useState, useRef} from 'react'
import {createPortal} from 'react-dom'
import {Modal} from 'react-bootstrap'
import {defaultCreateAppData, ICreateAppData} from './IAppModels'
import {StepperComponent} from '../../../assets/ts/components'
import {KTSVG} from '../../../helpers'
import {Step1} from './steps/Step1'
import {Step2} from './steps/Step2'
import {Step3} from './steps/Step3'
import {Step4} from './steps/Step4'
import {Step5} from './steps/Step5'
type Props = {
show: boolean
handleClose: () => void
}
const modalsRoot = document.getElementById('root-modals') || document.body
const CreateAppModal = ({show, handleClose}: Props) => {
const stepperRef = useRef<HTMLDivElement | null>(null)
const stepper = useRef<StepperComponent | null>(null)
const [data, setData] = useState<ICreateAppData>(defaultCreateAppData)
const [hasError, setHasError] = useState(false)
const loadStepper = () => {
stepper.current = StepperComponent.createInsance(stepperRef.current as HTMLDivElement)
}
const updateData = (fieldsToUpdate: Partial<ICreateAppData>) => {
const updatedData = {...data, ...fieldsToUpdate}
setData(updatedData)
}
const checkAppBasic = (): boolean => {
if (!data.appBasic.appName || !data.appBasic.appType) {
return false
}
return true
}
const checkAppDataBase = (): boolean => {
if (!data.appDatabase.databaseName || !data.appDatabase.databaseSolution) {
return false
}
return true
}
const prevStep = () => {
if (!stepper.current) {
return
}
stepper.current.goPrev()
}
const nextStep = () => {
setHasError(false)
if (!stepper.current) {
return
}
if (stepper.current.getCurrentStepIndex() === 1) {
if (!checkAppBasic()) {
setHasError(true)
return
}
}
if (stepper.current.getCurrentStepIndex() === 3) {
if (!checkAppDataBase()) {
setHasError(true)
return
}
}
stepper.current.goNext()
}
const submit = () => {
window.location.reload()
}
return createPortal(
<Modal
id='kt_modal_create_app'
tabIndex={-1}
aria-hidden='true'
dialogClassName='modal-dialog modal-dialog-centered mw-900px'
show={show}
onHide={handleClose}
onEntered={loadStepper}
>
<div className='modal-header'>
<h2>Create App</h2>
{/* begin::Close */}
<div className='btn btn-sm btn-icon btn-active-color-primary' onClick={handleClose}>
<KTSVG className='svg-icon-1' path='/media/icons/duotune/arrows/arr061.svg' />
</div>
{/* end::Close */}
</div>
<div className='modal-body py-lg-10 px-lg-10'>
{/*begin::Stepper */}
<div
ref={stepperRef}
className='stepper stepper-pills stepper-column d-flex flex-column flex-xl-row flex-row-fluid'
id='kt_modal_create_app_stepper'
>
{/* begin::Aside*/}
<div className='d-flex justify-content-center justify-content-xl-start flex-row-auto w-100 w-xl-300px'>
{/* begin::Nav*/}
<div className='stepper-nav ps-lg-10'>
{/* begin::Step 1*/}
<div className='stepper-item current' data-kt-stepper-element='nav'>
{/* begin::Wrapper*/}
<div className='stepper-wrapper'>
{/* begin::Icon*/}
<div className='stepper-icon w-40px h-40px'>
<i className='stepper-check fas fa-check'></i>
<span className='stepper-number'>1</span>
</div>
{/* end::Icon*/}
{/* begin::Label*/}
<div className='stepper-label'>
<h3 className='stepper-title'>Details</h3>
<div className='stepper-desc'>Name your App</div>
</div>
{/* end::Label*/}
</div>
{/* end::Wrapper*/}
{/* begin::Line*/}
<div className='stepper-line h-40px'></div>
{/* end::Line*/}
</div>
{/* end::Step 1*/}
{/* begin::Step 2*/}
<div className='stepper-item' data-kt-stepper-element='nav'>
{/* begin::Wrapper*/}
<div className='stepper-wrapper'>
{/* begin::Icon*/}
<div className='stepper-icon w-40px h-40px'>
<i className='stepper-check fas fa-check'></i>
<span className='stepper-number'>2</span>
</div>
{/* begin::Icon*/}
{/* begin::Label*/}
<div className='stepper-label'>
<h3 className='stepper-title'>Frameworks</h3>
<div className='stepper-desc'>Define your app framework</div>
</div>
{/* begin::Label*/}
</div>
{/* end::Wrapper*/}
{/* begin::Line*/}
<div className='stepper-line h-40px'></div>
{/* end::Line*/}
</div>
{/* end::Step 2*/}
{/* begin::Step 3*/}
<div className='stepper-item' data-kt-stepper-element='nav'>
{/* begin::Wrapper*/}
<div className='stepper-wrapper'>
{/* begin::Icon*/}
<div className='stepper-icon w-40px h-40px'>
<i className='stepper-check fas fa-check'></i>
<span className='stepper-number'>3</span>
</div>
{/* end::Icon*/}
{/* begin::Label*/}
<div className='stepper-label'>
<h3 className='stepper-title'>Database</h3>
<div className='stepper-desc'>Select the app database type</div>
</div>
{/* end::Label*/}
</div>
{/* end::Wrapper*/}
{/* begin::Line*/}
<div className='stepper-line h-40px'></div>
{/* end::Line*/}
</div>
{/* end::Step 3*/}
{/* begin::Step 4*/}
<div className='stepper-item' data-kt-stepper-element='nav'>
{/* begin::Wrapper*/}
<div className='stepper-wrapper'>
{/* begin::Icon*/}
<div className='stepper-icon w-40px h-40px'>
<i className='stepper-check fas fa-check'></i>
<span className='stepper-number'>4</span>
</div>
{/* end::Icon*/}
{/* begin::Label*/}
<div className='stepper-label'>
<h3 className='stepper-title'>Storage</h3>
<div className='stepper-desc'>Provide storage details</div>
</div>
{/* end::Label*/}
</div>
{/* end::Wrapper*/}
{/* begin::Line*/}
<div className='stepper-line h-40px'></div>
{/* end::Line*/}
</div>
{/* end::Step 4*/}
{/* begin::Step 5*/}
<div className='stepper-item' data-kt-stepper-element='nav'>
{/* begin::Wrapper*/}
<div className='stepper-wrapper'>
{/* begin::Icon*/}
<div className='stepper-icon w-40px h-40px'>
<i className='stepper-check fas fa-check'></i>
<span className='stepper-number'>5</span>
</div>
{/* end::Icon*/}
{/* begin::Label*/}
<div className='stepper-label'>
<h3 className='stepper-title'>Completed</h3>
<div className='stepper-desc'>Review and Submit</div>
</div>
{/* end::Label*/}
</div>
{/* end::Wrapper*/}
</div>
{/* end::Step 5*/}
</div>
{/* end::Nav*/}
</div>
{/* begin::Aside*/}
{/*begin::Content */}
<div className='flex-row-fluid py-lg-5 px-lg-15'>
{/*begin::Form */}
<form noValidate id='kt_modal_create_app_form'>
<Step1 data={data} updateData={updateData} hasError={hasError} />
<Step2 data={data} updateData={updateData} hasError={hasError} />
<Step3 data={data} updateData={updateData} hasError={hasError} />
<Step4 data={data} updateData={updateData} hasError={hasError} />
<Step5 />
{/*begin::Actions */}
<div className='d-flex flex-stack pt-10'>
<div className='me-2'>
<button
type='button'
className='btn btn-lg btn-light-primary me-3'
data-kt-stepper-action='previous'
onClick={prevStep}
>
<KTSVG
path='/media/icons/duotune/arrows/arr063.svg'
className='svg-icon-3 me-1'
/>{' '}
Previous
</button>
</div>
<div>
<button
type='button'
className='btn btn-lg btn-primary'
data-kt-stepper-action='submit'
onClick={submit}
>
Submit{' '}
<KTSVG
path='/media/icons/duotune/arrows/arr064.svg'
className='svg-icon-3 ms-2 me-0'
/>
</button>
<button
type='button'
className='btn btn-lg btn-primary'
data-kt-stepper-action='next'
onClick={nextStep}
>
Next Step{' '}
<KTSVG
path='/media/icons/duotune/arrows/arr064.svg'
className='svg-icon-3 ms-1 me-0'
/>
</button>
</div>
</div>
{/*end::Actions */}
</form>
{/*end::Form */}
</div>
{/*end::Content */}
</div>
{/* end::Stepper */}
</div>
</Modal>,
modalsRoot
)
}
export {CreateAppModal}
I would like to trigger CreateAppModal but cannot for the life of me get my head around it. Any help would be greatly appreciated!

You need to share the source code from CreateAppModal so we can know what it does and whats the relation with setItemIdForUpdate.

Related

Convert existing Formik form into multistep

I have a basic form opening in a modal, but need to convert this form to a multi-step inside the modal. I just cannot get my head around how this would work. Any help would be greatly appreciated!
Form:
import {FC, useState} from 'react'
import * as Yup from 'yup'
import {useFormik} from 'formik'
import {isNotEmpty, /*toAbsoluteUrl*/} from '../../../../../../_metronic/helpers'
import {initialUser, User} from '../core/_models'
import clsx from 'clsx'
import {useListView} from '../core/ListViewProvider'
import {UsersListLoading} from '../components/loading/UsersListLoading'
import {createUser, updateUser} from '../core/_requests'
import {useQueryResponse} from '../core/QueryResponseProvider'
type Props = {
isUserLoading: boolean
user: User
}
const editUserSchema = Yup.object().shape({
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Email is required'),
name: Yup.string()
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Name is required'),
})
const AddPropForm: FC<Props> = ({user, isUserLoading}) => {
const {setItemIdForUpdate} = useListView()
const {refetch} = useQueryResponse()
const [userForEdit] = useState<User>({
...user,
avatar: user.avatar || initialUser.avatar,
role: user.role || initialUser.role,
position: user.position || initialUser.position,
name: user.name || initialUser.name,
email: user.email || initialUser.email,
})
const cancel = (withRefresh?: boolean) => {
if (withRefresh) {
refetch()
}
setItemIdForUpdate(undefined)
}
// const blankImg = toAbsoluteUrl('/media/svg/avatars/blank.svg')
// const userAvatarImg = toAbsoluteUrl(`/media/${userForEdit.avatar}`)
const formik = useFormik({
initialValues: userForEdit,
validationSchema: editUserSchema,
onSubmit: async (values, {setSubmitting}) => {
setSubmitting(true)
try {
if (isNotEmpty(values.id)) {
await updateUser(values)
} else {
await createUser(values)
}
} catch (ex) {
console.error(ex)
} finally {
setSubmitting(true)
cancel(true)
}
},
})
return (
<>
<form id='kt_modal_add_user_form' className='form' onSubmit={formik.handleSubmit} noValidate>
{/* begin::Scroll */}
<div
className='d-flex flex-column scroll-y me-n7 pe-7'
id='kt_modal_add_user_scroll'
data-kt-scroll='true'
data-kt-scroll-activate='{default: false, lg: true}'
data-kt-scroll-max-height='auto'
data-kt-scroll-dependencies='#kt_modal_add_user_header'
data-kt-scroll-wrappers='#kt_modal_add_user_scroll'
data-kt-scroll-offset='300px'
>
{/* begin::Input group */}
{/* <div className='fv-row mb-7'> */}
{/* begin::Label */}
{/* <label className='d-block fw-bold fs-6 mb-5'>Avatar</label> */}
{/* end::Label */}
{/* begin::Image input */}
{/* <div
className='image-input image-input-outline'
data-kt-image-input='true'
style={{backgroundImage: `url('${blankImg}')`}}
> */}
{/* begin::Preview existing avatar */}
{/* <div
className='image-input-wrapper w-125px h-125px'
style={{backgroundImage: `url('${userAvatarImg}')`}}
></div> */}
{/* end::Preview existing avatar */}
{/* begin::Label */}
{/* <label
className='btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow'
data-kt-image-input-action='change'
data-bs-toggle='tooltip'
title='Change avatar'
>
<i className='bi bi-pencil-fill fs-7'></i>
<input type='file' name='avatar' accept='.png, .jpg, .jpeg' />
<input type='hidden' name='avatar_remove' />
</label> */}
{/* end::Label */}
{/* begin::Cancel */}
{/* <span
className='btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow'
data-kt-image-input-action='cancel'
data-bs-toggle='tooltip'
title='Cancel avatar'
>
<i className='bi bi-x fs-2'></i>
</span> */}
{/* end::Cancel */}
{/* begin::Remove */}
{/* <span
className='btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow'
data-kt-image-input-action='remove'
data-bs-toggle='tooltip'
title='Remove avatar'
>
<i className='bi bi-x fs-2'></i>
</span> */}
{/* end::Remove */}
{/* </div> */}
{/* end::Image input */}
{/* begin::Hint */}
{/* <div className='form-text'>Allowed file types: png, jpg, jpeg.</div> */}
{/* end::Hint */}
{/* </div> */}
{/* end::Input group */}
{/* begin::Input group */}
<div className='fv-row mb-7'>
{/* begin::Label */}
<label className='required fw-bold fs-6 mb-2'>Full Name</label>
{/* end::Label */}
{/* begin::Input */}
<input
placeholder='Full name'
{...formik.getFieldProps('name')}
type='text'
name='name'
className={clsx(
'form-control form-control-solid mb-3 mb-lg-0',
{'is-invalid': formik.touched.name && formik.errors.name},
{
'is-valid': formik.touched.name && !formik.errors.name,
}
)}
autoComplete='off'
disabled={formik.isSubmitting || isUserLoading}
/>
{formik.touched.name && formik.errors.name && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.name}</span>
</div>
</div>
)}
{/* end::Input */}
</div>
{/* end::Input group */}
{/* begin::Input group */}
<div className='fv-row mb-7'>
{/* begin::Label */}
<label className='required fw-bold fs-6 mb-2'>Email</label>
{/* end::Label */}
{/* begin::Input */}
<input
placeholder='Email'
{...formik.getFieldProps('email')}
className={clsx(
'form-control form-control-solid mb-3 mb-lg-0',
{'is-invalid': formik.touched.email && formik.errors.email},
{
'is-valid': formik.touched.email && !formik.errors.email,
}
)}
type='email'
name='email'
autoComplete='off'
disabled={formik.isSubmitting || isUserLoading}
/>
{/* end::Input */}
{formik.touched.email && formik.errors.email && (
<div className='fv-plugins-message-container'>
<span role='alert'>{formik.errors.email}</span>
</div>
)}
</div>
{/* end::Input group */}
{/* begin::Input group */}
<div className='mb-7'>
{/* begin::Label */}
<label className='required fw-bold fs-6 mb-5'>Role</label>
{/* end::Label */}
{/* begin::Roles */}
{/* begin::Input row */}
<div className='d-flex fv-row'>
{/* begin::Radio */}
<div className='form-check form-check-custom form-check-solid'>
{/* begin::Input */}
<input
className='form-check-input me-3'
{...formik.getFieldProps('role')}
name='role'
type='radio'
value='Tenant'
id='kt_modal_update_role_option_0'
checked={true}
disabled={true}
/>
{/* end::Input */}
{/* begin::Label */}
<label className='form-check-label' htmlFor='kt_modal_update_role_option_0'>
<div className='fw-bolder text-gray-800'>Tenant</div>
<div className='text-gray-600'>
Create an invite for a tenant to register with Landlord Direct
</div>
</label>
{/* end::Label */}
</div>
{/* end::Radio */}
</div>
{/* end::Input row */}
{/* <div className='separator separator-dashed my-5'></div> */}
{/* begin::Input row */}
{/* <div className='d-flex fv-row'> */}
{/* begin::Radio */}
{/* <div className='form-check form-check-custom form-check-solid'> */}
{/* begin::Input */}
{/* <input
className='form-check-input me-3'
{...formik.getFieldProps('role')}
name='role'
type='radio'
value='Developer'
id='kt_modal_update_role_option_1'
checked={formik.values.role === 'Developer'}
disabled={formik.isSubmitting || isUserLoading}
/> */}
{/* end::Input */}
{/* begin::Label */}
{/* <label className='form-check-label' htmlFor='kt_modal_update_role_option_1'>
<div className='fw-bolder text-gray-800'>Developer</div>
<div className='text-gray-600'>
Best for developers or people primarily using the API
</div>
</label> */}
{/* end::Label */}
{/* </div> */}
{/* end::Radio */}
{/* </div> */}
{/* end::Input row */}
{/* <div className='separator separator-dashed my-5'></div> */}
{/* begin::Input row */}
{/* <div className='d-flex fv-row'> */}
{/* begin::Radio */}
{/* <div className='form-check form-check-custom form-check-solid'> */}
{/* begin::Input */}
{/* <input
className='form-check-input me-3'
{...formik.getFieldProps('role')}
name='role'
type='radio'
value='Analyst'
id='kt_modal_update_role_option_2'
checked={formik.values.role === 'Analyst'}
disabled={formik.isSubmitting || isUserLoading}
/> */}
{/* end::Input */}
{/* begin::Label */}
{/* <label className='form-check-label' htmlFor='kt_modal_update_role_option_2'>
<div className='fw-bolder text-gray-800'>Analyst</div>
<div className='text-gray-600'>
Best for people who need full access to analytics data, but don't need to update
business settings
</div>
</label> */}
{/* end::Label */}
{/* </div> */}
{/* end::Radio */}
{/* </div> */}
{/* end::Input row */}
{/* <div className='separator separator-dashed my-5'></div> */}
{/* begin::Input row */}
{/* <div className='d-flex fv-row'> */}
{/* begin::Radio */}
{/* <div className='form-check form-check-custom form-check-solid'> */}
{/* begin::Input */}
{/* <input
className='form-check-input me-3'
{...formik.getFieldProps('role')}
name='role'
type='radio'
value='Support'
id='kt_modal_update_role_option_3'
checked={formik.values.role === 'Support'}
disabled={formik.isSubmitting || isUserLoading}
/> */}
{/* end::Input */}
{/* begin::Label */}
{/* <label className='form-check-label' htmlFor='kt_modal_update_role_option_3'>
<div className='fw-bolder text-gray-800'>Support</div>
<div className='text-gray-600'>
Best for employees who regularly refund payments and respond to disputes
</div>
</label> */}
{/* end::Label */}
{/* </div> */}
{/* end::Radio */}
{/* </div> */}
{/* end::Input row */}
{/* <div className='separator separator-dashed my-5'></div> */}
{/* begin::Input row */}
{/* <div className='d-flex fv-row'> */}
{/* begin::Radio */}
{/* <div className='form-check form-check-custom form-check-solid'> */}
{/* begin::Input */}
{/* <input
className='form-check-input me-3'
{...formik.getFieldProps('role')}
name='role'
type='radio'
id='kt_modal_update_role_option_4'
value='Trial'
checked={formik.values.role === 'Trial'}
disabled={formik.isSubmitting || isUserLoading}
/> */}
{/* end::Input */}
{/* begin::Label */}
{/* <label className='form-check-label' htmlFor='kt_modal_update_role_option_4'>
<div className='fw-bolder text-gray-800'>Trial</div>
<div className='text-gray-600'>
Best for people who need to preview content data, but don't need to make any
updates
</div>
</label> */}
{/* end::Label */}
{/* </div> */}
{/* end::Radio */}
{/* </div> */}
{/* end::Input row */}
{/* end::Roles */}
</div>
{/* end::Input group */}
</div>
{/* end::Scroll */}
{/* begin::Actions */}
<div className='text-center pt-15'>
<button
type='reset'
onClick={() => cancel()}
className='btn btn-light me-3'
data-kt-users-modal-action='cancel'
disabled={formik.isSubmitting || isUserLoading}
>
Discard
</button>
<button
type='submit'
className='btn btn-primary'
data-kt-users-modal-action='submit'
disabled={isUserLoading || formik.isSubmitting || !formik.isValid || !formik.touched}
>
<span className='indicator-label'>Submit</span>
{(formik.isSubmitting || isUserLoading) && (
<span className='indicator-progress'>
Please wait...{' '}
<span className='spinner-border spinner-border-sm align-middle ms-2'></span>
</span>
)}
</button>
</div>
{/* end::Actions */}
</form>
{(formik.isSubmitting || isUserLoading) && <UsersListLoading />}
</>
)
}
export {AddPropForm}
The form wrapper:
import {useQuery} from 'react-query'
import {AddPropForm} from './AddPropForm'
import {isNotEmpty, QUERIES} from '../../../../../../_metronic/helpers'
import {useListView} from '../core/ListViewProvider'
import {getUserById} from '../core/_requests'
const AddPropModalFormWrapper = () => {
const {itemIdForUpdate, setItemIdForUpdate} = useListView()
const enabledQuery: boolean = isNotEmpty(itemIdForUpdate)
const {
isLoading,
data: user,
error,
} = useQuery(
`${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`,
() => {
return getUserById(itemIdForUpdate)
},
{
cacheTime: 0,
enabled: enabledQuery,
onError: (err) => {
setItemIdForUpdate(undefined)
console.error(err)
},
}
)
if (!itemIdForUpdate) {
return <AddPropForm isUserLoading={isLoading} user={{id: undefined}} />
}
if (!isLoading && !error && user) {
return <AddPropForm isUserLoading={isLoading} user={user} />
}
return null
}
export {AddPropModalFormWrapper}
The form I am trying replace the current form with:
mport React, {FC, useEffect, useRef, useState} from 'react'
import {Step1} from './steps/Step1'
import {Step2} from './steps/Step2'
import {Step3} from './steps/Step3'
import {Step4} from './steps/Step4'
import {Step5} from './steps/Step5'
import {KTSVG} from '../../../../_metronic/helpers'
import {StepperComponent} from '../../../../_metronic/assets/ts/components'
import {Formik, Form, FormikValues} from 'formik'
import {createAccountSchemas, ICreateAccount, inits} from './CreateAccountWizardHelper'
const Horizontal: FC = () => {
const stepperRef = useRef<HTMLDivElement | null>(null)
const stepper = useRef<StepperComponent | null>(null)
const [currentSchema, setCurrentSchema] = useState(createAccountSchemas[0])
const [initValues] = useState<ICreateAccount>(inits)
const [isSubmitButton, setSubmitButton] = useState(false)
const loadStepper = () => {
stepper.current = StepperComponent.createInsance(stepperRef.current as HTMLDivElement)
}
const prevStep = () => {
if (!stepper.current) {
return
}
setSubmitButton(stepper.current.currentStepIndex === stepper.current.totatStepsNumber! - 1)
stepper.current.goPrev()
setCurrentSchema(createAccountSchemas[stepper.current.currentStepIndex - 1])
}
const submitStep = (values: ICreateAccount, actions: FormikValues) => {
if (!stepper.current) {
return
}
setSubmitButton(stepper.current.currentStepIndex === stepper.current.totatStepsNumber! - 1)
setCurrentSchema(createAccountSchemas[stepper.current.currentStepIndex])
if (stepper.current.currentStepIndex !== stepper.current.totatStepsNumber) {
stepper.current.goNext()
} else {
stepper.current.goto(1)
actions.resetForm()
}
}
useEffect(() => {
if (!stepperRef.current) {
return
}
loadStepper()
}, [stepperRef])
return (
<div className='card'>
<div className='card-body'>
<div
ref={stepperRef}
className='stepper stepper-links d-flex flex-column pt-15'
id='kt_create_account_stepper'
>
<div className='stepper-nav mb-5'>
<div className='stepper-item current' data-kt-stepper-element='nav'>
<h3 className='stepper-title'>Account Type</h3>
</div>
<div className='stepper-item' data-kt-stepper-element='nav'>
<h3 className='stepper-title'>Account Info</h3>
</div>
<div className='stepper-item' data-kt-stepper-element='nav'>
<h3 className='stepper-title'>Business Info</h3>
</div>
<div className='stepper-item' data-kt-stepper-element='nav'>
<h3 className='stepper-title'>Billing Details</h3>
</div>
<div className='stepper-item' data-kt-stepper-element='nav'>
<h3 className='stepper-title'>Completed</h3>
</div>
</div>
<Formik validationSchema={currentSchema} initialValues={initValues} onSubmit={submitStep}>
{() => (
<Form className='mx-auto mw-600px w-100 pt-15 pb-10' id='kt_create_account_form'>
<div className='current' data-kt-stepper-element='content'>
<Step1 />
</div>
<div data-kt-stepper-element='content'>
<Step2 />
</div>
<div data-kt-stepper-element='content'>
<Step3 />
</div>
<div data-kt-stepper-element='content'>
<Step4 />
</div>
<div data-kt-stepper-element='content'>
<Step5 />
</div>
<div className='d-flex flex-stack pt-15'>
<div className='mr-2'>
<button
onClick={prevStep}
type='button'
className='btn btn-lg btn-light-primary me-3'
data-kt-stepper-action='previous'
>
<KTSVG
path='/media/icons/duotune/arrows/arr063.svg'
className='svg-icon-4 me-1'
/>
Back
</button>
</div>
<div>
<button type='submit' className='btn btn-lg btn-primary me-3'>
<span className='indicator-label'>
{!isSubmitButton && 'Continue'}
{isSubmitButton && 'Submit'}
<KTSVG
path='/media/icons/duotune/arrows/arr064.svg'
className='svg-icon-3 ms-2 me-0'
/>
</span>
</button>
</div>
</div>
</Form>
)}
</Formik>
</div>
</div>
</div>
)
}
export {Horizontal}
What would be the correct way of bringing in the multi step functionality of the new form whilst still having it open inside the modal?

Main checkbox selecting all cards when checked

I am building a component where I am grouping cards by regions. I have a checkbox by the region name and when its checked I want to be able to select all the cards in the region.
This is how my cards are displayed by region:
<div className="pl-14 text-black font-nunito mt-8 ml-3 text-2xl">
{_.map(_.keysIn(groups), (region) => {
return (
<>
<div className="flex justify-between">
<div className="flex">
<Checkbox
className="bg-transparent shadow-none text-black hover:bg-transparent"
color="primary"
/>
<p className="mt-1">{_.capitalize(region)}</p>
</div>
<div className="pr-16">
<Button variant="text" className="text-lightBlue">
View More
</Button>
</div>
</div>
<UserCards groupedUser={groups[region]} />
</>
);
})}
</div>
And my cards look like this:
const UserCards = ({ groupedUser }) => {
return groupedUser.map((user) => (
<div className="cardContainer">
<div className="card shadow-customShadow">
<Checkbox
key={user.email}
className="bg-transparent shadow-none text-black mb-14 hover:bg-transparent"
color="primary"
onChange={(event) => {
if (event.target.checked) {
const data = [...userEmails];
data.push(user.email);
setUserEmails(data);
} else {
const data = [...userEmails];
const index = data.indexOf(user.email);
data.splice(index, 1);
setUserEmails(data);
}
}}
checked={_.includes(userEmails, user.email)}
/>
<div>
<div className="mt-2 text-lg">
{information stored here}
</div>
<div className="mt-2 text-lg">
{information stored here}
</div>
</div>
</div>
</div>
));
};
How can I tell the region check box to check all the cards?

How can I display my data dynamically onclick event in React

I'm creating a movies app with React and Redux, in each movie card I have some information about the movie like the title, image, and a button(buy a ticket). The idea is when I click on the button of each card I want to get the same image and title of the card and display it on the same page on another card that going to pop up so the user can choose the quantity and continue.
How can I get the data from the movie card onclick and transform it to another card as a pop-up?
what do you think
Single movie card Component
const SingleMovieCard = ({ id, title, poster_path, overview, toggleHandler }) => {
const [selected, isSelected] = useState(null);
return (
<article key={id} className="card">
<div key={id} onMouseEnter={() => isSelected(id)} onMouseLeave={() => isSelected(null)}>
<img src={`${ImgPath}` + poster_path} alt={title} className="image" />
{selected === id && <video src="./Trailers/SpaceJam.mp4" autoPlay={true} loop muted />}
</div>
<div className="body-card">
<h1>{title}</h1>
<p>{`${overview.substring(0, 200)}...`}</p>
</div>
<div className="services">
<FiShare2 className="icon" />
<FiHeart className="icon" />
<div className="btn-icon-container">
<BiShoppingBag className="btn-icon" />
<button onClick={() => toggleHandler()}>Buy Ticket</button>
</div>
</div>
</article>
)
}
export default SingleMovieCard;
Pop-up movie card
const PopUpMovie = ({showClass, toggleHandler}) => {
const moviesList = useSelector((state)=> state.allMovies.movies);
return (
<div className={`pop-up-container ${showClass}`}>
<nav className="pop-up">
<GrClose className="pop-up-close" onClick={()=> toggleHandler()}/>
<div className="product-details">
<div className="img-container">
<img src="./Pictures/FreeGuy.jpg" alt="FreeGuy" />
</div>
<div className="product info">
<h1 className="title">Free Guy movie</h1>
<div className="quantity">
<h4>Quantity</h4>
<span>4</span>
</div>
<h5 className="prix">11$</h5>
<button className="btn-checkout">Continue to checkout</button>
</div>
</div>
</nav>}
</div>
)
}
export default PopUpMovie;
you can use Modal from react-bootstrap
Example:
import { Modal } from "react-bootstrap";
const PopUpMovie = ({ showClass, toggleHandler }) => {
const modalContent = (
<div className={`pop-up-container ${showClass}`}>
<nav className="pop-up">
<GrClose className="pop-up-close" onClick={() => toggleHandler()} />
<div className="product-details">
<div className="img-container">
<img src="./Pictures/FreeGuy.jpg" alt="FreeGuy" />
</div>
<div className="product info">
<h1 className="title">Free Guy movie</h1>
<div className="quantity">
<h4>Quantity</h4>
<span>4</span>
</div>
<h5 className="prix">11$</h5>
<button className="btn-checkout">Continue to checkout</button>
</div>
</div>
</nav>
</div>
)
const moviesList = useSelector((state) => state.allMovies.movies);
return (
<Modal
id="order-modal-close"
backdrop="static"
show={showClass}
size={"md"}
dialogClassName="modal-90w"
onHide={toggleHandler}
>
<Modal.Header closeButton>
<Modal.Title>Movie</Modal.Title>
</Modal.Header>
<Modal.Body >{modalContent}</Modal.Body>
{modalFooter}
</Modal>
)
}

Display different values in a popup in React

I am trying to have a popup for editing profile information in react, and I want there to be a button by each value that will allow a user to edit that specific value. The popup works, except it will only display the last value that I have put in. I think it is because I need to reset the state each time the button is clicked, but I am still fairly new to react so I am not sure how to do it.
I will add my code, however it is pulling some information from a local database, so let me know if you need me to remove things.
Here is the component for the popup
import React from 'react'
const Popup = props => {
console.log(props)
return(
<div className='popup-box'>
<div className='box'>
<span className='close-icon' onClick={props.handleClose}>x</span>
{props.content}
</div>
</div>
)
}
export default Popup
And here is the component page where the popup appears
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { getUser } from '../apiClient'
import Nav from './Nav'
import EditPopup from './EditPopup'
export default function UserProfile (props) {
const [isOpen, setIsOpen] = useState(false)
const togglePopup = () => {
setIsOpen(!isOpen)
}
const [user, setUser] = useState({
user: []
})
useEffect(() => {
getUser(props.match.params.id)
.then((res) => {
setUser(res)
})
.catch((error) => {
console.log('error', error.message)
})
}, [])
return (
<div className='globalBackground'>
<Nav />
<div className='UserInfoForm'>
<div className='profile-heading' >
<h1>General User Information</h1>
</div>
<div className='profile-Pic' >
<div className='profile-pic-heading'>
<h2>Profile Picture</h2>
</div>
<div className='profile-pic-display'>
<img src={user.profilePic} style={{ width: '150px', height: '150px' }}
alt=''
/>
</div>
</div>
<div className='UsernameEdit'>
<h2>Username</h2>
<p>{user.username}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Username</b>
<div className='userNameEditInput'>
<input className='usernameEdit' placeholder={user.username} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
<div />
<div className='EmailEdit'>
<h2>Email</h2>
<p>{user.email}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Email</b>
<div className='emailEditInput'>
<input className='emailEdit' placeholder={user.email} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='CountryEdit'>
<h2>Country</h2>
<p>{user.country}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Country</b>
<div className='countryEditInput'>
<input className='countryEdit' placeholder={user.country} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='RegionEdit'>
<h2>Region</h2>
<p>{user.region}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Region</b>
<div className='regionEditInput'>
<input className='regionEdit' placeholder={user.email} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='HandicapEdit'>
<h2>Handicap</h2>
<p>{user.handicap}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Handicap</b>
<div className='handicapEditInput'>
<input className='handicapEdit' placeholder={user.handicap} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
</div>
</div>
</div>
)
}
Let me know if there's any other code needed, any help would be greatly appreciated :--)
You can remove the state from the UserProfile and move it inside the Popup Component.
import React from 'react';
const Popup = (props) => {
const [toggle, setToggle] = useState(false);
const togglePopup = () => setToggle((prevToggle) => !prevToggle);
return (
<>
<input type="button" value="Edit" onClick={togglePopup} />
{toggle && (
<div className="popup-box">
<div className="box">
<span className="close-icon" onClick={togglePopup }>
x
</span>
{props.content}
</div>
</div>
)}
</>
);
};
export default Popup;
You can then use EditPopup as below in the UserProfile.
{
<div className='UsernameEdit'>
<h2>Username</h2>
<p>{user.username}</p>
<EditPopup
content={<>
<b>Edit Your Username</b>
<div className='userNameEditInput'>
<input className='usernameEdit' placeholder={user.username} />
</div>
<button>Save Changes</button>
</>
}
/>
<div />
}

findDOMNode is deprecated in StrictMode, Reactjs Modal Component

Reactjs shows this error when i open modal that is from another component
"index.js:1 Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Modal which is inside StrictMode. Instead, add a ref directly to the element you want to reference."
I've tried alot of other solutions but none of them work in my case
my code file:
class Routes extends Component {
componentDidMount() {
console.log('Component did mount!')
}
loginModalRef = ({ handleShow }) => {
this.showModal = handleShow;
}
onLoginClick = () => {
this.showModal();
}
ShopersModalRef = ({ handleShoperShow }) => {
this.showShoperModal = handleShoperShow;
}
onShopersClick = () => {
this.showShoperModal();
}
//ChargeModalRef = ({ handleChargeShow }) => {
// this.showChargeModal = handleChargeShow;
//}
// onChargeClick = () => {
// this.showChargeModal();
// }
render() {
return (
<div>
{/*<chargeFeeModal ref={this.ChargeModalRef}></chargeFeeModal>*/}
<FormModal ref={this.loginModalRef}></FormModal>
<ShopersModal ref={this.ShopersModalRef}></ShopersModal>
<AppBar position="sticky" className="appbar">
<Toolbar className="NavbarTop">
<div className='row w-100'>
<div className="col-4 LogoOrBack">
<section className="leftBox shopname ml-4">
<Typography className="typography">
{Text}
</Typography>
</section>
</div>
<div className="col-4 centered">
<section className="centerBox">
<Typography className="typography">
<b>Stores</b>
</Typography>
</section>
</div>
<div className="col-4 righted">
<section className="rightBox">
<Typography className="typography">
<Button className="primary btn AccountBtn" onClick={this.onLoginClick}>
<img alt="user account avatar" src={require('../../../assets/images/placeholder_account.png')} className="buttonImage" /> Account
</Button>
<Button className="primary btn" onClick={this.onLoginClick}>
<i className="fa fa-cart-plus cart"></i>
</Button>
</Typography>
</section>
</div>
</div>
</Toolbar>
<Toolbar>
<div className='row w-100'>
<div className='col-lg-4'>
{(() => {
//Javascript for changing buttons
switch (history.location.pathname) {
case "/": return <Button onClick={this.onLoginClick} className="primary postalCodeBtn" >
<img alt="home icon" src={require('../../../assets/images/homeicon.png')} className="buttonImage" /> <b>M4b 146, CA</b> <i className="fa fa-chevron-down downIco"></i>
</Button>;
default: return (
<Button onClick={this.onShopersClick} className="primary postalCodeBtn" >
<img alt="home icon" src={require('../../../assets/images/time.png')} className="buttonImage" /> <b style={{ textTransform: 'capitalize' }}>Shoppers Occupied</b>
</Button>
);
}
})()}
</div>
<div className="col-lg-4 centered p-1 pl-4" >
<div className="searchContainer">
<i className="fa fa-search searchIcon"></i>
<input className="searchBox" type="search" name="search" placeholder="Search Stores" />
</div>
</div>
{TabsShowOrNo}
</div>
</Toolbar>
</AppBar>
<AnimatedSwitch
atEnter={{ opacity: 0 }}
atLeave={{ opacity: 0 }}
atActive={{ opacity: 1 }}
className="switch-wrapper"
>
<Route exact path="/" component={HomePage} />
<Route path='/store/orders/' component={OrdersPage} />
<Route path='/store/aisles/' component={AislesPage} />
<Route path="/store/featured" component={SingleStorePage} />
<Route component={NotFound} />
</AnimatedSwitch>
</div >
)
}
}```
any help will be appreciate

Resources