React Native Material Dropdown:如何基于JSON实现自动填充/选择下拉框
Got it, let's walk through building a linked auto-fill/select dropdown system using your diagnosis JSON structure. Since you mentioned a renderingMenu() function, I'll cover both React (a common framework for such UIs) and vanilla JavaScript so you can adapt it to your setup.
Step 1: Preprocess Your Data
First, we need to turn your raw diagnosis array into a set of lookup maps. This lets us quickly find related values when a user selects an option, instead of digging through the array every time. Here's a function to do that:
const processDiagnosisData = (diagnosis) => { // Extract each group from the diagnosis array const kodeGroup = diagnosis.find(item => item.name === "kode"); const priCatGroup = diagnosis.find(item => item.name === "Primary Category"); const locationGroup = diagnosis.find(item => item.name === "Location"); // Map kode values to their related category and location const kodeMap = {}; kodeGroup.value.forEach(kodeItem => { const kodeValue = kodeItem.value; kodeMap[kodeValue] = { primaryCategory: priCatGroup.value.find(cat => cat.id === kodeValue)?.value || null, location: locationGroup.value.find(loc => loc.id === kodeValue)?.value || null }; }); // Reverse maps for selecting from category or location first const priCatMap = {}; priCatGroup.value.forEach(cat => { priCatMap[cat.value] = { kode: cat.id, location: locationGroup.value.find(loc => loc.id === cat.id)?.value || null }; }); const locationMap = {}; locationGroup.value.forEach(loc => { locationMap[loc.value] = { kode: loc.id, primaryCategory: priCatGroup.value.find(cat => cat.id === loc.id)?.value || null }; }); // Also extract flat option lists for dropdowns return { kodeMap, priCatMap, locationMap, kodeOptions: kodeGroup.value.map(item => item.value), priCatOptions: priCatGroup.value.map(item => item.value), locationOptions: locationGroup.value.map(item => item.value) }; };
Step 2: Implement the Dropdowns (React Example)
If you're using React, here's a complete component that handles state management and auto-fill logic:
import { useState, useEffect } from 'react'; const DiagnosisDropdowns = ({ diagnosis }) => { const [dataMaps, setDataMaps] = useState(null); const [selectedKode, setSelectedKode] = useState(''); const [selectedPriCat, setSelectedPriCat] = useState(''); const [selectedLocation, setSelectedLocation] = useState(''); // Process data when the component mounts or diagnosis data changes useEffect(() => { if (diagnosis) { setDataMaps(processDiagnosisData(diagnosis)); } }, [diagnosis]); // Auto-fill category and location when kode is selected const handleKodeChange = (e) => { const kode = e.target.value; setSelectedKode(kode); if (dataMaps?.kodeMap[kode]) { setSelectedPriCat(dataMaps.kodeMap[kode].primaryCategory); setSelectedLocation(dataMaps.kodeMap[kode].location); } else { setSelectedPriCat(''); setSelectedLocation(''); } }; // Auto-fill kode and location when category is selected const handlePriCatChange = (e) => { const priCat = e.target.value; setSelectedPriCat(priCat); if (dataMaps?.priCatMap[priCat]) { setSelectedKode(dataMaps.priCatMap[priCat].kode); setSelectedLocation(dataMaps.priCatMap[priCat].location); } else { setSelectedKode(''); setSelectedLocation(''); } }; // Auto-fill kode and category when location is selected const handleLocationChange = (e) => { const location = e.target.value; setSelectedLocation(location); if (dataMaps?.locationMap[location]) { setSelectedKode(dataMaps.locationMap[location].kode); setSelectedPriCat(dataMaps.locationMap[location].primaryCategory); } else { setSelectedKode(''); setSelectedPriCat(''); } }; if (!dataMaps) return <div>Loading...</div>; return ( <div style={{ display: 'flex', gap: '2rem', padding: '1rem' }}> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>Kode:</label> <select value={selectedKode} onChange={handleKodeChange} style={{ padding: '0.5rem' }}> <option value="">Select a kode</option> {dataMaps.kodeOptions.map(kode => ( <option key={kode} value={kode}>{kode}</option> ))} </select> </div> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>Primary Category:</label> <select value={selectedPriCat} onChange={handlePriCatChange} style={{ padding: '0.5rem' }}> <option value="">Select a category</option> {dataMaps.priCatOptions.map(cat => ( <option key={cat} value={cat}>{cat}</option> ))} </select> </div> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>Location:</label> <select value={selectedLocation} onChange={handleLocationChange} style={{ padding: '0.5rem' }}> <option value="">Select a location</option> {dataMaps.locationOptions.map(loc => ( <option key={loc} value={loc}>{loc}</option> ))} </select> </div> </div> ); }; // Usage example const diagnosisData = [ {"name": "kode", "value": [ {"value": "kode1"},{"value": "kode2"},{"value": "kode3"} ]}, {"name": "Primary Category", "value": [ {"value": "PriCat1","id": "kode1"}, {"value": "PriCat2","id": "kode2"}, {"value": "PriCat3","id": "kode3"} ]}, {"name": "Location", "value": [ {"value": "Loc1","id": "kode1"}, {"value": "Loc2","id": "kode2"}, {"value": "Loc3","id": "kode3"} ]} ]; // Render with <DiagnosisDropdowns diagnosis={diagnosisData} />
Step 3: Vanilla JavaScript Alternative
If you're not using a framework, here's how to implement the same logic with plain JS and HTML:
HTML
<div style="display: flex; gap: 2rem; padding: 1rem;"> <div> <label style="display: block; margin-bottom: 0.5rem;">Kode:</label> <select id="kode-select" style="padding: 0.5rem;"> <option value="">Select a kode</option> </select> </div> <div> <label style="display: block; margin-bottom: 0.5rem;">Primary Category:</label> <select id="priCat-select" style="padding: 0.5rem;"> <option value="">Select a category</option> </select> </div> <div> <label style="display: block; margin-bottom: 0.5rem;">Location:</label> <select id="location-select" style="padding: 0.5rem;"> <option value="">Select a location</option> </select> </div> </div>
JavaScript
const diagnosisData = [ {"name": "kode", "value": [ {"value": "kode1"},{"value": "kode2"},{"value": "kode3"} ]}, {"name": "Primary Category", "value": [ {"value": "PriCat1","id": "kode1"}, {"value": "PriCat2","id": "kode2"}, {"value": "PriCat3","id": "kode3"} ]}, {"name": "Location", "value": [ {"value": "Loc1","id": "kode1"}, {"value": "Loc2","id": "kode2"}, {"value": "Loc3","id": "kode3"} ]} ]; // Process the data const { kodeMap, priCatMap, locationMap, kodeOptions, priCatOptions, locationOptions } = processDiagnosisData(diagnosisData); // Get dropdown elements const kodeSelect = document.getElementById('kode-select'); const priCatSelect = document.getElementById('priCat-select'); const locationSelect = document.getElementById('location-select'); // Populate options for each dropdown const populateOptions = (selectElement, options) => { options.forEach(optionValue => { const option = document.createElement('option'); option.value = optionValue; option.textContent = optionValue; selectElement.appendChild(option); }); }; populateOptions(kodeSelect, kodeOptions); populateOptions(priCatSelect, priCatOptions); populateOptions(locationSelect, locationOptions); // Add change event listeners kodeSelect.addEventListener('change', (e) => { const kode = e.target.value; if (kodeMap[kode]) { priCatSelect.value = kodeMap[kode].primaryCategory; locationSelect.value = kodeMap[kode].location; } else { priCatSelect.value = ''; locationSelect.value = ''; } }); priCatSelect.addEventListener('change', (e) => { const cat = e.target.value; if (priCatMap[cat]) { kodeSelect.value = priCatMap[cat].kode; locationSelect.value = priCatMap[cat].location; } else { kodeSelect.value = ''; locationSelect.value = ''; } }); locationSelect.addEventListener('change', (e) => { const loc = e.target.value; if (locationMap[loc]) { kodeSelect.value = locationMap[loc].kode; priCatSelect.value = locationMap[loc].primaryCategory; } else { kodeSelect.value = ''; priCatSelect.value = ''; } });
Key Notes
- Flexibility: The code supports selecting from any dropdown (kode, category, or location) and auto-filling the other two. If you only need one-way linking (e.g., kode drives the others), you can remove the reverse maps and their event handlers.
- Error Handling: The optional chaining (
?.) and null checks ensure the code doesn't break if a matching value isn't found (though your data seems consistent, it's good practice). - Reusability: The
processDiagnosisDatafunction is reusable across different implementations, so you can plug it into your existingrenderingMenu()logic easily.
内容的提问来源于stack exchange,提问作者flix

