react-vmodel
v0.2.0
Published
a vue v-model like usage for react with ts prompt
Downloads
14
Maintainers
Readme
react-vmodel
A vue v-model similar usage for react . Easy to access deep path with ts prompt.
Usage
Bind to Component
import { makeVModel ,useVModel} from 'react-vmodel'
export default function Demo() {
const [data,setData]=useState(
{ name:'example',
tasks:[{id:1,name:'test'}]
}
)
const vModel=makeVModel(data,setData)
//or define with hook
// const [vModel,data,setData]=useVModel({
// { name:'example',
// tasks:[{id:1,name:'test'}]
// }
// )
return<>
{/* All Bind with react-vmodel */}
<CustomComponent {...vModel()}/>
{/* //--not with */}
<CustomComponent value={data} onChange={(e)=>{
setData(e.target?e.target.value:e)
}}/>
{/* //Path Bind with react-vmodel */}
<CustomComponent2 {...vModel("tasks[0].name")}/>
{/* //--not with */}
<CustomComponent2
value={data.tasks[0].name}
onChange={(e) => {
const clone = structuredClone(data);
clone.tasks[0].name = e.target?e.target.value:e;
setData(clone);
}}
/>
</>
}
Bind to input
Text
import { makeVModel } from 'react-vmodel'
export default function Demo() {
const [text,setText]=useState('Hello World')
const vModel=makeVModel(text,setText)
return<>
<input {...vModel()}></input>
{/* //trim */}
<input {...vModel.trim()}></input>
{/* //number */}
<input type="number" {...vModel()}></input>
{/* //or */}
<input {...vModel.number()}></input>
</>
}
Checkbox
True-False
import { makeVModel } from 'react-vmodel'
export default function Demo() {
const [checked,setChecked]=useState(false)
const vModel=makeVModel(checked,setChecked)
return<>
{/* //true-false */}
<input type='checkbox' {...vModel.checked()}></input>
{/* //true 1 false 0 */}
<input type='checkbox' {...vModel.checked({trueValue:1,falseValue:0})}></input>
</>
}
CheckedList
import { makeVModel } from "react-vmodel"
export default function Demo() {
const [checkedList, setCheckedList] = useState([])
const vModel = makeVModel(checkedList, setCheckedList)
return (
<>
{["one", "two", "three"].map((op) => (
<input
key={op}
type="checkbox"
{...vModel.checklist({ value: op })}
></input>
))}
</>
)
}
Radio
import { makeVModel } from "react-vmodel"
export default function Demo() {
const [selected, setSelected] = useState("")
const vModel = makeVModel(selected, setSelected)
return (
<>
{["one", "two", "three"].map((op) => (
<input
key={op}
type="radio"
{...vModel.checked({ value: op })}
></input>
))}
</>
)
}
Select
import { makeVModel } from "react-vmodel"
export default function Demo() {
const [selected, setSelected] = useState("")
const vModel = makeVModel(selected, setSelected)
return (
<>
{
<select {...vModel()}>
{["one", "two", "three"].map((op) => {
return (
<option key={op} value={op}>
{op}
</option>
)
})}
</select>
}
</>
)
}
Advance Usage
import { makeVModel } from 'react-vmodel'
export default function Demo() {
const [checked,setChecked]=useState(false)
const vModel=makeVModel(checked,setChecked)
return<>
{/* //true 1 false 0 */}
<input type='checkbox' {...vModel.checked({trueValue:1,falseValue:0})}></input>
{/* custom the same function */}
<input type='checkbox' {...vModel((value, onChange) => ({
checked: value === 1,
value:String(value===1),
onChange: (e) => onChange(e.target.checked ? 1 : 0)
}))} />
</>
}
Full Example
npx degit https://github.com/leafio/react-vmodel/examples react-vmodel-examples
Vanilla Form
import { useEffect, useState } from "react"
import { makeVModel } from "react-vmodel"
export default function DemoVanilla() {
const [form, setForm] = useState({
name: "demo",
gender: "male",
hobbies: [],
job: {
id: 0,
year: 1,
},
projects: [
{
name: "First",
isFinished: 1,
},
{
name: "Last",
isFinished: 0,
},
],
})
const vModel = makeVModel(form, setForm)
useEffect(() => {
console.log(form)
})
return (
<form className="flex flex-col ">
<label className="mb-1">
<span className="w-24 inline-block">Name:</span>
<input type="text" className=" border" {...vModel("name")} />
</label>
<div className="mb-1">
<span className="w-24 inline-block">Gender:</span>
<label>
Male
<input
type="radio"
className=" border"
{...vModel.checked("gender", { value: "male" })}
/>
</label>
<label>
Female
<input
type="radio"
className=" border"
{...vModel.checked("gender", { value: "female" })}
/>
</label>
</div>
<label className="mb-1">
<span className="w-24 inline-block">Hobbies:</span>
{hobbyOptions.map((h) => (
<label key={h}>
{h}
<input
type="checkbox"
className=" border"
{...vModel.checklist("hobbies", { value: h })}
/>
</label>
))}
</label>
<label className="mb-1">
<span className="w-24 inline-block">Job:</span>
<select {...vModel.number("job.id")}>
{jobOptions.map((job) => {
return (
<option key={job.value} value={job.value}>
{job.label}
</option>
)
})}
</select>
</label>
<label className="mb-1">
<span className="w-24 inline-block">Experience:</span>
<input
type="number"
className=" border"
{...vModel("job.year")}
/>
</label>
<div className="mb-1">
<span className="w-24 inline-block">Projects:</span>
{form.projects.map((p, index) => (
<label key={p.name}>
<span>{p.name}</span>
<input
type="checkbox"
{...vModel.checked(
`projects[${index}].isFinished`,
{ trueValue: 1, falseValue: 0 }
)}
/>
</label>
))}
</div>
</form>
)
}
const hobbyOptions = ["film", "sports", "music"]
const jobOptions = [
{
label: "Front End Developer",
value: 0,
},
{
label: "Back End Developer",
value: 1,
},
{
label: "Test Engineer",
value: 2,
},
]
Ant Design
import { Checkbox, Form, Input, InputNumber, Radio, Select, Switch } from "antd"
import { useEffect, useState } from "react"
import { makeVModel } from "react-vmodel"
export default function DemoAntd() {
const [form, setForm] = useState({
name: "demo",
join: "yes",
gender: "male",
hobbies: [],
job: {
id: 0,
year: 1,
},
projects: [
{
name: "First",
isFinished: 1,
},
{
name: "Last",
isFinished: 0,
},
],
})
const vModel = makeVModel(form, setForm)
useEffect(() => {
console.log(form)
})
return (
<Form
className="flex flex-col "
labelCol={{ span: 4 }}
labelAlign="left"
>
<Form.Item label="Name:">
<Input type="text" {...vModel("name")} />
</Form.Item>
<Form.Item label="Join:">
<Switch
{...vModel.checked("join", {
trueValue: "yes",
falseValue: "no",
})}
/>
</Form.Item>
<div className="mb-1">
<Form.Item label="Gender:">
<Radio {...vModel.checked("gender", { value: "male" })}>
Male
</Radio>
<Radio {...vModel.checked("gender", { value: "female" })}>
Female
</Radio>
</Form.Item>
</div>
<Form.Item label="Hobbies">
{hobbyOptions.map((h) => (
<Checkbox
key={h}
{...vModel.checklist("hobbies", { value: h })}
>
{h}
</Checkbox>
))}
</Form.Item>
<Form.Item label="Job">
<Select {...vModel.number("job.id")} options={jobOptions} />
</Form.Item>
<Form.Item label="Experience">
<InputNumber {...vModel("job.year")} />
</Form.Item>
<Form.Item label="Projects">
{form.projects.map((p, index) => (
<Checkbox
key={p.name}
{...vModel.checked(`projects[${index}].isFinished`, {
trueValue: 1,
falseValue: 0,
})}
>
{p.name}{" "}
</Checkbox>
))}
</Form.Item>
</Form>
)
}
const hobbyOptions = ["film", "sports", "music"]
const jobOptions = [
{
label: "Front End Developer",
value: 0,
},
{
label: "Back End Developer",
value: 1,
},
{
label: "Test Engineer",
value: 2,
},
]
Material UI
import {
Checkbox,
FormControl,
FormControlLabel,
FormLabel,
Input,
MenuItem,
Radio,
Select,
Switch,
} from "@mui/material"
import { useEffect, useState } from "react"
import { makeVModel } from "react-vmodel"
export default function DemoMui() {
const [form, setForm] = useState({
name: "demo",
join: "yes",
gender: "male",
hobbies: [],
job: {
id: 0,
year: 1,
},
projects: [
{
name: "First",
isFinished: 1,
},
{
name: "Last",
isFinished: 0,
},
],
})
const vModel = makeVModel(form, setForm)
useEffect(() => {
console.log(form)
})
return (
<form className="flex flex-col ">
<FormControl>
<FormLabel>Name:</FormLabel>
<Input type="text" {...vModel("name")} />
</FormControl>
<FormControl>
<FormLabel>Join:</FormLabel>
<Switch
{...vModel.checked("join", {
trueValue: "yes",
falseValue: "no",
})}
/>
</FormControl>
<FormControl>
<FormLabel>Gender:</FormLabel>
<div className="flex">
<FormControlLabel
label={"Male"}
control={
<Radio
{...vModel.checked("gender", {
value: "male",
})}
/>
}
/>
<FormControlLabel
label={"Female"}
control={
<Radio
{...vModel.checked("gender", {
value: "female",
})}
/>
}
/>
</div>
</FormControl>
<FormControl>
<FormLabel>Hobbies:</FormLabel>
<div className="flex">
{hobbyOptions.map((h) => (
<FormControlLabel
key={h}
label={h}
control={
<Checkbox
{...vModel.checklist("hobbies", {
value: h,
})}
/>
}
/>
))}
</div>
</FormControl>
<FormControl>
<FormLabel>Job:</FormLabel>
<Select {...vModel.number("job.id")}>
{jobOptions.map((job) => {
return (
<MenuItem key={job.value} value={job.value}>
{job.label}
</MenuItem>
)
})}
</Select>
</FormControl>
<FormControl>
<FormLabel>Experience:</FormLabel>
<Input type="number" {...vModel("job.year")} />
</FormControl>
<FormControl>
<FormLabel>Projects:</FormLabel>
<div className="flex">
{form.projects.map((p, index) => (
<FormControlLabel
key={p.name}
label={p.name}
control={
<Checkbox
{...vModel.checked(
`projects[${index}].isFinished`,
{ trueValue: 1, falseValue: 0 }
)}
/>
}
/>
))}
</div>
</FormControl>
</form>
)
}
const hobbyOptions = ["film", "sports", "music"]
const jobOptions = [
{
label: "Front End Developer",
value: 0,
},
{
label: "Back End Developer",
value: 1,
},
{
label: "Test Engineer",
value: 2,
},
]
Installation
npm install react-vmodel