Can you watch for onBlur? #8523
-
When using watch, is it possible to detect when a field has blurred?
In this code typescript accepts "blur" and a valid type but the type seems to only ever be "change" |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
You can either use:
|
Beta Was this translation helpful? Give feedback.
-
I found an easier way. Just wrap the input item around a div and use the onBlur item of the div. See below: console.log('clicked')}>
|
Beta Was this translation helpful? Give feedback.
-
For people seeing this in the future, this works: const { setValue } = useForm({
input1: "enter a value"
});
return (
<input
onBlur={ (e) => setValue( "input1", e.target.value ) }
/>
) The docs say it's best to register the input first before using |
Beta Was this translation helpful? Give feedback.
-
I have an error and I don't know how I can solve it using the hook form, I would like my address fields to be self-completed when the address name is entered, these fields to validate first time in case I don't need to do any action in the field To be able to send this data, what can I do? import React, { useEffect, useRef, useState } from 'react'
import { MdGpsFixed } from 'react-icons/md'
import { Box, Grid, TextField, Typography } from '@mui/material'
import FormInput from '../ui/FormInput'
import MaskedInput from '../ui/MaskedInput'
import { ZipcodeMask } from '@/app/utils/Masks'
import CustomButton from '../ui/CustomButton'
const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY
const mapApiJs = 'https://maps.googleapis.com/maps/api/js'
const geocodeJson = 'https://maps.googleapis.com/maps/api/geocode/json'
function loadAsyncScript(src) {
return new Promise((resolve) => {
const script = document.createElement('script')
Object.assign(script, {
type: 'text/javascript',
async: true,
src,
})
script.addEventListener('load', () => resolve(script))
document.head.appendChild(script)
})
}
const extractAddress = (place) => {
const address = {
city: '',
state: '',
zip: '',
district: '',
street: '',
street_number: '',
plain() {
const city = this.city ? this.city + ', ' : ''
const zip = this.zip ? this.zip + ', ' : ''
const state = this.state ? this.state + ', ' : ''
return city + zip + state + this.district
},
}
if (!Array.isArray(place?.address_components)) {
return address
}
console.log(place.address_components)
place.address_components.forEach((component) => {
const types = component.types
const value = component.long_name
if (types.includes('administrative_area_level_2')) {
address.city = value
}
if (types.includes('administrative_area_level_1')) {
address.state = value
}
if (types.includes('postal_code')) {
address.zip = value
}
if (types.includes('sublocality_level_1')) {
address.district = value
}
if (types.includes('route')) {
address.street = value
}
if (types.includes('street_number')) {
address.street_number = value
}
})
return address
}
function EventLocationForm({ register, errors }) {
const [street, setStreet] = useState('')
const searchInput = useRef(null)
const [addressName, setAddressName] = useState('')
const [zipcode, setZipcode] = useState('')
const [address, setAddress] = useState('')
const [number, setNumber] = useState('')
const [complement, setComplement] = useState('')
const [district, setDistrict] = useState('')
const [city, setCity] = useState('')
const [province, setProvince] = useState('')
const initMapScript = () => {
if (window.google) {
return Promise.resolve()
}
const src = `${mapApiJs}?key=${apiKey}&libraries=places&v=weekly`
return loadAsyncScript(src)
}
const onChangeAddress = (autocomplete) => {
const place = autocomplete.getPlace()
setAddress(extractAddress(place))
}
const initAutocomplete = () => {
if (!searchInput.current) return
const autocomplete = new window.google.maps.places.Autocomplete(
searchInput.current,
)
autocomplete.setFields(['address_component', 'geometry'])
autocomplete.addListener('place_changed', () =>
onChangeAddress(autocomplete),
)
}
const reverseGeocode = ({ latitude: lat, longitude: lng }) => {
const url = `${geocodeJson}?key=${apiKey}&latlng=${lat},${lng}`
searchInput.current.value = 'Getting your location...'
fetch(url)
.then((response) => response.json())
.then((location) => {
const place = location.results[0]
const _address = extractAddress(place)
setAddress(_address)
searchInput.current.value = _address.plain()
})
}
const findMyLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
reverseGeocode(position.coords)
})
}
}
useEffect(() => {
initMapScript().then(() => initAutocomplete())
}, [])
useEffect(() => {
if (address) {
setAddressName(address.street)
setZipcode(address.zip)
setStreet(address.street)
setNumber(address.street_number)
setComplement('')
setDistrict(address.district)
setCity(address.city)
setProvince(address.state)
}
}, [address])
return (
<Grid container spacing={2}>
<Typography
sx={{ m: '1rem 0 0 1rem', color: '#FF0240' }}
variant="h6"
gutterBottom
>
Informe o endereço completo do local onde será realizado o seu evento
</Typography>
<Grid item xs={6}>
<Box mt={2}>
<TextField
{...register(`addressName`)}
name="addressName"
error={errors.addressName && errors.addressName.message}
helperText={errors.addressName && errors.addressName.message}
inputRef={searchInput}
label="Informe o endereço ou o nome do local do evento"
/>
<CustomButton onClick={findMyLocation}>
<MdGpsFixed />
</CustomButton>
<p>
Cidade: <span>{address.city}</span>
</p>
<p>
Estado: <span>{address.state}</span>
</p>
<p>
CEP: <span>{address.zip}</span>
</p>
<p>
Bairro: <span>{address.district}</span>
</p>
<p>
Rua: <span>{address.street}</span>
</p>
<p>
Número : <span>{address.street_number}</span>
</p>
<MaskedInput
sx={{ mt: 2 }}
name="zipcode"
value={address.zip}
label="CEP"
mask={ZipcodeMask}
/>
<TextField
sx={{ mt: 2 }}
{...register(`address`)}
name="address"
value={street}
onChange={(e) => setStreet(e.target.value)}
error={errors.address && errors.address.message}
helperText={errors.address && errors.address.message}
fullWidth
label="AV./RUA"
/>
<Grid container spacing={2}>
<Grid item xs={6}>
<TextField
{...register(`number`)}
name="number"
sx={{ mt: 2 }}
value={number}
onChange={(e) => setN(e.target.value)}
error={errors.number && errors.number.message}
helperText={errors.number && errors.number.message}
fullWidth
label="Número"
/>
</Grid>
<Grid item xs={6}>
<FormInput
sx={{ mt: 2 }}
name="complement"
required
fullWidth
label="Complemento"
/>
</Grid>
</Grid>
<TextField
sx={{ mt: 2 }}
{...register(`district`)}
name="district"
required
value={district}
onChange={(e) => setDistrict(e.target.value)}
error={errors.district && errors.district.message}
helperText={errors.district && errors.district.message}
fullWidth
label="Bairro"
/>
<Grid container spacing={2}>
<Grid item xs={6}>
<TextField
sx={{ mt: 2 }}
{...register(`city`)}
name="city"
required
value={city}
onChange={(e) => setCity(e.target.value)}
error={errors.city && errors.city.message}
helperText={errors.city && errors.city.message}
fullWidth
label="Cidade"
/>
</Grid>
<Grid item xs={6}>
<TextField
sx={{ mt: 2 }}
{...register(`province`)}
name="province"
required
value={province}
onChange={(e) => setProvince(e.target.value)}
error={errors.province && errors.province.message}
helperText={errors.province && errors.province.message}
fullWidth
label="Estado"
/>
</Grid>
</Grid>
</Box>
</Grid>
<Grid item xs={6}>
<Box mt={2}>
{/* <GoogleMap
options={mapOptions}
zoom={14}
center={mapCenter}
mapTypeId={google.maps.MapTypeId.ROADMAP}
mapContainerStyle={{ width: '100%', height: '420px' }}
onLoad={(map) => console.log('Map Loaded')}
>
<Marker
position={mapCenter}
onLoad={() => console.log('Marker Loaded')}
/>
</GoogleMap> */}
</Box>
</Grid>
</Grid>
)
}
export default EventLocationForm |
Beta Was this translation helpful? Give feedback.
watch
API isn't concerned about the events; it's a simple subscription to a field value.You can either use:
onBlur
event callback for a specific inputonBlur
event callback for whatever inputblur
event