昨天介紹了pdf表單和 native-base的欄位。今天來實作 UI吧
我們先請 AI 產生範例讓我們參考一下,看一下看起來的感覺操作看看是否合用。
幫我做一頁 範例,我想看一下 native-base 所有的 forms 表單資料欄位 範本
AI 幫我們用 native-base 產生了一個表單的範例。而且按了 submit 還會印在 console.log 。
import React, { useState } from 'react';
import { Box, Button, FormControl, Input, Select, Switch, Checkbox, Text, VStack, ScrollView } from 'native-base';
const FormExample = () => {
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [age, setAge] = useState('');
const [gender, setGender] = useState('');
const [isSubscribed, setIsSubscribed] = useState(false);
const [hobbies, setHobbies] = useState([]);
const handleSubmit = () => {
console.log({
username,
email,
password,
age,
gender,
isSubscribed,
hobbies,
});
};
return (
<ScrollView>
<Box p="4" safeArea>
<VStack space={4}>
<FormControl isRequired>
<FormControl.Label>Username</FormControl.Label>
<Input
placeholder="Enter your username"
value={username}
onChangeText={setUsername}
/>
</FormControl>
<FormControl isRequired>
<FormControl.Label>Email</FormControl.Label>
<Input
placeholder="Enter your email"
value={email}
keyboardType="email-address"
onChangeText={setEmail}
/>
</FormControl>
<FormControl isRequired>
<FormControl.Label>Password</FormControl.Label>
<Input
placeholder="Enter your password"
value={password}
secureTextEntry
onChangeText={setPassword}
/>
</FormControl>
<FormControl>
<FormControl.Label>Age</FormControl.Label>
<Input
placeholder="Enter your age"
value={age}
keyboardType="numeric"
onChangeText={setAge}
/>
</FormControl>
<FormControl>
<FormControl.Label>Gender</FormControl.Label>
<Select
selectedValue={gender}
minWidth="200"
accessibilityLabel="Choose Gender"
placeholder="Choose Gender"
onValueChange={setGender}
>
<Select.Item label="Male" value="male" />
<Select.Item label="Female" value="female" />
<Select.Item label="Other" value="other" />
</Select>
</FormControl>
<FormControl>
<FormControl.Label>Subscribe to Newsletter</FormControl.Label>
<Switch
isChecked={isSubscribed}
onToggle={() => setIsSubscribed(!isSubscribed)}
/>
</FormControl>
<FormControl>
<FormControl.Label>Select Your Hobbies</FormControl.Label>
<Checkbox.Group
onChange={setHobbies}
value={hobbies}
accessibilityLabel="Choose your hobbies"
>
<Checkbox value="reading" my={2}>
Reading
</Checkbox>
<Checkbox value="traveling" my={2}>
Traveling
</Checkbox>
<Checkbox value="gaming" my={2}>
Gaming
</Checkbox>
<Checkbox value="cooking" my={2}>
Cooking
</Checkbox>
</Checkbox.Group>
</FormControl>
<Button mt="4" colorScheme="teal" onPress={handleSubmit}>
Submit
</Button>
</VStack>
</Box>
</ScrollView>
);
};
export default FormExample;
產生出來的畫面,感覺還不錯。
填寫資料測試看看。
填寫的資料也都會正確送出,還不錯。可以開始下一步實作。
{
"username": "",
"email": "2323",
"password": "",
"age": "",
"gender": "female",
"isSubscribed": false,
"hobbies": [
"gaming",
"traveling"
]
}
因為其實 chp555 欄位非常多,如果我們這樣直接做的話,會非常長,我覺得會使用者體驗不太好?在 native-base 有個元件叫 Accordion(收合?) 一樣請 AI實作一下。
幫我加上收合區域
可以看到AI 幫我們加上 Accordin 這個元件,主要用來顯示可展開和摺疊的內容區塊。
[!tip]
- Accordion 是外層容器,用來包住多個可展開的項目。
- Accordion.Item 是每個單獨的項目,包含兩個部分:
- Accordion.Summary:項目的標題,使用者點擊後會展開或摺疊內容。
- Accordion.Details:當展開時顯示的詳細內容,在這裡包含一些表單元素。
const FormExample = () => {
......
return (
<ScrollView>
<Box p="4" safeArea>
....
<Accordion>
<Accordion.Item>
<Accordion.Summary>
<Text>Additional Information</Text>
<Accordion.Icon />
</Accordion.Summary>
<Accordion.Details>
<FormControl>
<FormControl.Label>Age</FormControl.Label>
....
</FormControl>
<FormControl>
<FormControl.Label>Subscribe to Newsletter</FormControl.Label>
....
</FormControl>
......
</Accordion.Details>
</Accordion.Item>
</Accordion>
.....
</Box>
</ScrollView>
);
};
export default FormExample;
這樣收合與展開看起來感覺不錯。
展開 | 收合 |
我們直接修改剛剛的範例,來做一下大概 pdf 表單的欄位會像是這樣。剩下來的工作我覺得就是工作了,因為需要把表單的的欄位一個一個生成出來。也可以請 AI實作,但這邊就會要先釐清需求。
![[Pasted image 20241009143603.png]]
這邊比較不一樣的是我有自己我做一個多選欄位的元件,讓多選是一個多的對話視窗,還有加上限制選擇的數量。\
import React, {useState} from 'react';
import {
Box,
FormControl,
Modal,
Button,
Checkbox,
Text,
Pressable,
} from 'native-base';
interface Option {
value: string;
label: string;
}
interface MultiSelectProps {
label: string;
options: Option[];
onSelectionChange: (values: string[]) => void;
max?: number;
defaultValue?: string[];
}
const MultiSelect: React.FC<MultiSelectProps> = ({
label,
options = [],
onSelectionChange,
max,
defaultValue = [],
}) => {
const [showModal, setShowModal] = useState(false);
const [selectedValues, setSelectedValues] = useState<string[]>(defaultValue);
const handleSelectionChange = (values: string[]) => {
setSelectedValues(values);
onSelectionChange(values);
};
const renderText = (values: string[]) => {
if (!values || values.length === 0) {
return 'Select your options ';
}
const selectedOptions = options.filter(option =>
values.includes(option.value),
);
return selectedOptions.map(option => option.label).join(',');
};
return (
<FormControl isRequired>
<FormControl.Label>{label}</FormControl.Label>
<Pressable onPress={() => setShowModal(true)}>
<Box
borderWidth={1}
borderColor="gray.300"
borderRadius="md"
p="2"
flexDirection="row"
alignItems="center">
<Text flex={1}>{renderText(defaultValue)}</Text>
</Box>
</Pressable>
<Modal isOpen={showModal} onClose={() => setShowModal(false)}>
<Modal.Content maxWidth="400px">
<Modal.CloseButton />
<Modal.Header>{label}</Modal.Header>
<Modal.Body>
<Checkbox.Group
accessibilityLabel={`Choose your ${label}`}
onChange={handleSelectionChange}
defaultValue={defaultValue}>
{options?.map(option => (
<Checkbox
key={option.value}
value={option.value}
isDisabled={
!!(max && selectedValues.length >= max) &&
!selectedValues.includes(option.value)
}>
{option.label}
</Checkbox>
))}
</Checkbox.Group>
</Modal.Body>
<Modal.Footer>
<Button onPress={() => setShowModal(false)}>Save</Button>
</Modal.Footer>
</Modal.Content>
</Modal>
</FormControl>
);
};
export default MultiSelect;
我們實作了一下表單欄位,明天我們會來設計一下表單的資料庫結構與開api CRUD 接著串接道前端就完成表單的部分啦~~!
用說的比較簡單QQ