How to focus input element in html in React popup behaviour - css

I have a React Typescript app and when the user clicks a button, they should be prompted with a model dialog that asks them for a comment. I would like the textbox input control of this modal to be focussed when they click the button, so they can start typing straight away - but can't figure out how to do that. Can anyone suggest?
Also as a second question - is there a way I can bind the "Enter" keystroke to close the modal? Escape is built in as a special behaviour character in NPM react-modal but I would like Enter to submit the OK button.
My react modal component (using NPM react-modal)
<ReactModal
isOpen={this.state.dialogOpen}
contentLabel="Example Modal"
className="Modal"
overlayClassName="Overlay"
shouldCloseOnEsc={true}
shouldReturnFocusAfterClose={true}
role="dialog"
onRequestClose={this.handleCloseModal}
shouldCloseOnOverlayClick={false}
// tslint:disable
parentSelector={() => document.body}
>
<div className="Modal-Container">
<div style={{flex:0.4}}>
<div className="Panel-header-left">
Please enter a reason for rejecting
</div>
</div>
<div style={{flex:0.6}}>
<input type="textbox" name="ModalInput" value={this.state.comment} onChange={ this.handleCommentChange.bind(this)} />
</div>
<div>
<div className="Panel-header-right">
<button className="Action-Button" onClick={(e) => this.handleCloseModal()}>Cancel</button>
<button className="Action-Button" onClick={(e) => this.processRejectComments()}>OK</button>
</div>
</div>
</div>
</ReactModal>
and my button click to load the modal
private doReject()
{
if (this.gridApi.getSelectedNodes().length > 0)
{
this.setState({comment: ""});
this.handleOpenModal();
}
}

1. To focus the input of the modal, first set reference of <input> then call input.focus() in onAfterOpen() of react-modal
<ReactModal
isOpen={this.state.dialogOpen}
onAfterOpen={() => this._input.focus()}
>
<input ref={input => this._input = input}/>
</ReactModal>
2. To close modal on user press Enter, wrap the <input> by a <form>, then close model in its onSubmit()
<ReactModal
isOpen={this.state.dialogOpen}
>
<form onSubmit={() => this.setState({dialogOpen: false})>
<input {...} />
</form>
</ReactModal>
Here's CodeSandbox: https://codesandbox.io/s/wn18lvjlx7

Related

How to change the appearance of a button when it is clicked to show an arrow, using css

I want to change the appearance of a button when it its clicked to show an arrow coming out of it. I would like to do it using css. I am building a react application using typescript.
When the next button is clicked the arrow should be removed from the first one and go to the next one.
I have included a picture of the desired outcome.
Here is an example of 2 of the buttons:
<div className="button-container">
<Button
className="text-white font-nunito text active"
onClick={() => onFieldAdd('textField')}
>
<TextFieldsIcon />
<p> Text Box</p>
</Button>
<Button
className="text-white font-nunito text mx-2 pr-15"
onClick={() => onFieldAdd('imageField')}
disabled={!!formId}
>
<AddPhotoAlternateIcon />
<p> Image</p>
</Button>
</div>
This could be the solution you're looking for:
import { useState } from "react";
const YourComponentName = () => {
const [selectedBtn, setSelectedBtn] = useState(null);
const hanldeClick = (e) => setSelectedBtn(e.target.id);
return (
<div>
<button id="btn1" onClick={hanldeClick} className={selectedBtn === "btn1" ? "hasArrow" : ""}>
Button 1
</button>
<button id="btn2" onClick={hanldeClick} className={selectedBtn === "btn2" ? "hasArrow" : ""}>
Button 2
</button>
// SAME THING FOR THE REST OF THE BUTTONS
</div>
)
}
export default YourComponentName;
Just customize it to suit your use case.
Here, I am initializing a state called selectedBtn to null by default, and listening for onClick events on all of the buttons to change that state to the clicked button id. Once it changes, component will rerenders and the CSS class hasArrow will be added to the appropriate button element by checking if selectedBtn state value is equal to the button id, with the help of the ternary conditional operator ?:.

Materialize css modal validation

I am using Materialize css to design my post. Suppose I have a form in modal and I and post it to server.
In that form I am checking if all fields are having value.
<form>
<div class="input-field">
<input type="text" id="title" class="validate" required="" aria-required="true">
<label for="title">Title</label>
</div>
The title field is required. But when I click on a submit button in modal it is closing even if title field has empty value. Is there any way to keep the modal open for validation error in Materialize css v1.
Think about this is in separate steps. The form submission only takes place at the end of the chain, when our criteria have been met.
User Submits form
We check the form
We feedback to user
Depending on the results of 2, we may either go back to step 1, or on to step 3.
Modal Structure:
<div id="modal1" class="modal">
<div class="modal-content">
<div class="input-field">
<input type="text" id="title" class="validate" required="" aria-required="true">
<label for="title">Title</label>
<span class="helper-text" data-error="Please enter your name" data-success="Thankyou!"></span>
</div>
</div>
<div class="modal-footer">
<a id="submit-button" href="#!" class="btn">Submit</a>
close
</div>
</div>
We add optional helper-text span for user feedback, as per the documentation.
The Javascript:
document.addEventListener('DOMContentLoaded', function() {
// init modal
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
// get button
var button = document.querySelector('#submit-button');
// Run our own function when clicked
button.addEventListener("click", checkForm);
// Function checks for input
function checkForm() {
var input = document.querySelector('#title');
if(input.value) {
// submit form
// add valid class to show helper
input.classList.add('valid');
// close modal
instances[0].close();
// clear form
input.value = '';
// remove valid class
input.classList.remove('valid');
} else {
// prompt user for input
input.classList.add('invalid');
}
}
});
We grab the value of the text input, and based on that, add a valid or invalid class - this is the built in materialize stuff that hides or shows the relevant message that we set in data-error and data-success.
The only thing you need to add to this is the actual form submission - so something like form.submit().
Codepen.

Adding a required in a basic for of an input and button

I tried to add a required element (when the box become red if not text is inside) on my form but without success, I installed react-strap, Bootstrap. when I apply many changed it didn't work for no reason
and it's just not moving if someone know why I would be happy.
render() {
return (
<div>
<form class="needs-validation" novalidate>
<InputGroup size="sm">
<InputGroupAddon addonType="append" className="m-2">
<Input
className="form-control"
placeholder="Add a new To-Do. "
onChange={(e) => this.updateInput(e.target.value)}
value={this.state.input}
onKeyPress={this.handleKeyPress}
required
/>
<Button
color="primary"
size="sm"
className="add-todo"
onClick={this.handleAddTodo}
>
Add
</Button>
</InputGroupAddon>
</InputGroup>
</form>
</div>
);
}
export default connect(null, { addTodo })(AddTodo);
// export default AddTodo;
What you are doing is passing required as a prop to your class Input. You need to add the html tag when the field renders, i.e. in Input.js:
return (
<input ... required={this.props.required}>
)
i think you should add the 'is-invalid' class to the input element if that field is empty.
https://getbootstrap.com/docs/4.0/components/forms/?#server-side

How to Disable submit button on form after user click in the submit button angular 6

This is what I want my button to do .
I want my button to be disable until the user enter all the values need it in the form.
Once the user enter all the values in the form the user should be able to click in the submit button.
Then after the user click in the submit button this button should be disables again
I try this something like this
html
<div class="field is-grouped">
<p class="control">
<button class="button is-info"
[disabled]="!aFormGroup.dirty || !FormGroup.valid "
type="submit"
onClick= "this.disabled=true"
>Submit</button>
</p>
</div
ts
submit() {..}
my button get disable when the user click in the button but I don't get any results from the api .
It seem that nothing is send to the api
This works
html
<div class="field is-grouped">
<p class="control">
<button class="button is-info"
[disabled]="!aFormGroup.dirty || !FormGroup.valid "
type="submit"
>Submit</button>
</p>
ts
submit() {..}
but my button is not disable after the user click on it
You can define a public boolean field in the component and bind the value to the [disabled] attribute in the html.
[disabled]="!aFormGroup.dirty || !aFormGroup.valid || isDisabled"
and set the value to true in the submit method.
Here is a little example https://stackblitz.com/edit/angular-ygdag8

Bootstrap navbar drop down login in the React way

I am building a login feature into a bootstrap navbar, and using the boostrap dropdown component. By default, this component closes on a click. To handle login errors, however, the component needs to stay open to display an error message. Through JQuery, it's possible to either prevent the close and then show the desired error message. But this doesn't feel right in React.
But what is the right way to do this in React? It seems that, if there's a login error, I want to
1) Set a set a state variable with the correct error message
2) Call setState to force a re-render
3) On re-render, show the drop-down as open and with the error message
But how can I show the drop-down as open on the re-render? Is there a property that will force it to start opened? Below is the HTML
<li>
<a id="nav-login" className="nav-link dropdown-toggle" href="#" data-toggle="dropdown">Login</a>
<div className="useraccount-dropdown-menu dropdown-menu" onClick={this.preventClose} >
<p className="title">LOG IN</p>
<form action="#" onSubmit={this.login} method="post" acceptCharset="UTF-8">
<label>USER NAME</label>
<input className="textfield" ref="username" placeholder="userone#email.com" type="text"/>
<label>PASSWORD</label>
<input className="textfield" ref="password" placeholder="**********" type="password"/>
<button className="btn btn-primary btn-nativelogin" type="submit">Sign in</button>
</form>
</div>
</li>
Right now, onSubmit, the following function gets sets the error message - and calls setState. This is changing the state variable, but bootstrap closes the component so the re-render never happens.
login : function(e){
e.preventDefault();
Meteor.loginWithPassword(this.refs.username.value, this.refs.password.value, (error) => {
if(error){
this.setState({errorMsg: error.reason});
}else{
this.setState({isLoggedIn: true});
}
});
},
How can I prevent the component from closing? I tried adding an onClick event listener to the overall drop-down component and that calls stopPropagation.
preventClose: function(e){
e.preventDefault();
e.stopPropagation();
},
But this is not preventing the close.
You can handle the click event. Check out this demo
$('#myDropdown .dropdown-menu').on({
"click":function(e){
e.stopPropagation();
}
});
I hope this helps.

Resources