SMUI sveltekit Textfield always null on form submit - sveltekit

I've just started using SMUI and sveltekit and I'm running into an issue . . .
I'm using the Textfield component in a login form, and this doesn't work:
<form method="post">
<Textfield variant="outlined" bind:value={username} label="Username"></Textfield>
<Textfield type="password" variant="outlined" bind:value={password} label="Password">
<Button type="submit">Login</Button>
</form>
Which posts to a page with this code:
export const actions = {
default: async ({ cookies, request }) => {
const data = await request.formData()
const username = data.get('username')
const password = data.get('password')
}
}
username and password are both null on submit.
To make this work, I insert "shadow" hidden fields
<form method="post">
<Textfield variant="outlined" bind:value={username} label="Username"></Textfield>
<input type="hidden" name="username" value={username}>
<Textfield type="password" variant="outlined" bind:value={password} label="Password">
<input type="hidden" name="password" value={password}>
<Button type="submit">Login</Button>
</form>
And then I get values for username and password. I'm assuming I don't need to do this - what am I doing wrong?
Edit 2022-10-17
It was suggested that I add a "name" parameter to the textfields like so:
<Textfield variant="outlined" value="" name="username"></Textfield>
<Textfield type="password" variant="outlined" value="" name="password"></Textfield>
That also doesn't work - when the values come over for the form they are both null.
Other ideas?

You can specify the name of the nested input element like so:
<Textfield input$name="username" ... />

Form fields are only submitted if they have a name attribute. The bindings are completely irrelevant, you only need them if you want to use the values elsewhere in the code or component.

Related

I have prevented default behaviour of form on submit, but it still sending post request automatically to current url

<form
className="login"
onSubmit={e => {
alert('hey getting called')
e.preventDefault()
this.authorizeUser(e)
}}
>
<input
type="text"
name="email"
onChange={e => this.handleInputChange(e)}
value={email}
className="login-input"
placeholder="Email Adress"
autoFocus
/>
<input
type="password"
name="password"
onChange={e => this.handleInputChange(e)}
value={password}
className="login-input"
placeholder="Password"
/>
<button
type="submit"
style={{height: '37px', float: 'left'}}
className="login-button"
>
Login
</button>
</form>
code is not reaching up to alert statement.
instead i see url changes to ->
http://localhost:3000/signin?email=testUSer%40abx.in&password=1234567 and page gets refreshed
This issue is happening after i updated react version from 16.9 to 17.0.0.
UPDATE
When i add the listener via add event listener inside componentDidMount() then suddenly it started working as expected!
still wonder why the onSubmit directly on form didn't work

Antd form: passing dynamic id alongside form-values

im working on a commenting system. Every ID has some comments. If I want to make a new comment, the ID has to be passed alongside the form-values.
ID is being rendered dynamically:
{data && data.formations.map(formation =>
<Row>
<Col span={2}>
<p>ID: {formation.id}</p>
</Col>
...
Form has a Textarea, and the value is being passed automatically due the name prop in Form.Item.
<Form onFinish={onFinish}>
<Form.Item name="comment">
<TextArea rows={4} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">Add comment</Button>
</Form.Item>
</Form>
Idealy, I want the ID passed alongside the values in the following function OnFinish:
const onFinish = (values) *id somehwere here* => {
console.log(values)
}
How to achieve this? Thanks in advance!
You could solve this by adding an hidden field which holds the ID :
<Form onFinish={onFinish}>
<Form.Item name="comment">
<TextArea rows={4} />
</Form.Item>
<Form.Item name="id">
<Input type="hidden" value={formation.id} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">Add comment</Button>
</Form.Item>
</Form>
Then in the onFinish callback you should get a new property id in the values object.
This is the common way to pass known/readonly values alongside form values (in the non SPA / synchronous web world, eg PHP).

react-hook-form can't see change value by click on button to reset input

Component with input and button to reset input TexInputComponent:
<input
type={type}
name={name}
ref={register}
/>
<button
type="button"
onClick={clearInput}>
Reset input
</button>
const clearInput = () => {
document.querySelector(`#${name}`).value = null;
};
I'm using TexInputComponent inside form in another component:
<TexInputComponent
name="title"
defaultValue={data?.title}
register={register({ required: 'Title is required.' })}
error={errors.title}
/>
Now when I click submit on form react-hook-form return me error e.g 'Title is required!'. When I writing something in TexInputComponent, then error disapear.
The problem is when I writing text and click button to reset input. The clearInput method is executed (this method changing value to null) Now should displaying error, but I thing the react hook form can't see value changing.
How I can fix it?
Your clearInput() doesn't work because you don't provide a unique id so it can't find the input element to reset. So change to this:
<input
id={name} // --> add this line to fix
type={type}
name={name}
ref={register}
/>
However there are other ways to easily reset the form without having to define your own reset method:
Use <input type='reset' /> to create a reset button that resets all fields in a form.
Use reset() function from useForm hook to reset a specific field:
const { register, reset } = useForm();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>First name</label>
<input type="text" name="firstName" ref={register} />
<label>Last name</label>
<input type="text" name="lastName" ref={register} />
<input type="submit" />
<button
type="button"
onClick={() => reset({ firstName: "default name" })}
>
Reset first name
</button>
</form>
);

How can I set the textfield as disabled and when typed, it will be enabled again?

How can I code this where the textfield's original state will be disabled and then when typed in, it will be enabled. Then that textfield will be the only one be updated when submitted?
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
value={displayName}
fullWidth
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
disabled
margin="dense"
type="text"
label="address"
value={address}
fullWidth
onChange={(e) => setAddress(e.target.value)}
/>
<Button type="submit">Update</Button>
</form>
Even though you disable one input, It still re-render everytime you typing (because you setState on change). You can use ref like this to prevent unnecessary render.
const nameRef = useRef(null);
const addressRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
console.log(addressRef.current.value);
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
fullWidth
inputRef={nameRef}
/>
<TextField
margin="dense"
type="text"
label="address"
fullWidth
inputRef={addressRef}
/>
<Button type="submit">Update</Button>
</form>
)
You can add a validation on handleSubmit because if a textfield is disabled, you need another action to make it enable and it's not ok for the user also.
You can try to add something like:
const handleSubmit = () => {
if ((displayName === "" || displayName == null) && (address == "" || address === null) {
//show error for user that both fields have to be completed
} else {
//do the form submit
}
}

Using bootstrap components with react-hook validation form

I've been working with React for a while, and decided to try out react-hook. I'm trying to make a simple form with some simple validation, but it seems like the validation does not apply to bootstrap components. For the 'regular' input, it works fine, but for the form.control it's not working(The validation is skipped). Saw one solution where you wrap the componenet in a controller, as shown bellow, but i got the same result. Any ideas?
Thanks.
function Example(){
const { register, handleSubmit, control, errors } = useForm();
const onSubmit = (data:any) => {
console.log(data)
}
return(
<Form onSubmit={handleSubmit(onSubmit)}>
<Form.Label column>Name</Form.Label>
<Controller as={<Form.Control/>} name="firstName" control={control} ref={register({required: true})} defaultValue="" />
{errors.firstName && <p>This is required</p>}
<input name="lastName" className="form-control" ref={register({required: true})} />
{errors.lastName && <p>This is required</p>}
<input type="submit" ref={register({required: true})}/>
</Form>
)
}

Resources