Disabled a button when input filed is empty without using a handler - reactjs

I tried to disabled a button when input filed is empty without using a handler.
Before I check the condition, I only want to simply enabled the button when input is changed (not yet check if content of input) but I did see the state is changed (I can see it in the alert) but the button is never enabled (I can see that in debugger)
constructor(props) {
super(props);
this.state = {'enableAdd':false}
}
Text: <input id="textInput" type="text" onChange={()=>{this.state.enableAdd=true;alert(this.state.enableAdd)}}/>
<button onClick={this.addTODO} disabled={!this.state.enableAdd} style={{"paddingLeft":"7px"}}>Add</button>
Any idea?
thanks

You need to check, how to update state value?
Instead of changing the state value directly this.state.enableAdd = true; use setState.
Like this:
this.setState({enableAdd=true});
Check the DOC how to use state in React and for other details.
Check the working example of your problem:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {'enableAdd':false};
this.addTODO = this.addTODO.bind(this);
}
addTODO(){
console.log('clicked');
}
render(){
return <div>
<input id="textInput" type="text" onChange={(e) => this.setState({enableAdd: e.target.value != ''})}/>
<button onClick={this.addTODO} disabled={!this.state.enableAdd}>Add</button>
</div>
}
}
ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'/>

Related

Auto focus first time on loading page

There is a input text in center in which I want to focus when the page loads, so I have used componentDidMount() and set the focus.
componentDidMount() {
this.inputBar.focus();
}
.
.
<input type="text" ref={(element) => { this.inputBar = element; }}>
but it isn't working as a sidebar pops in as the page loads and shifts the focus from the center input.
I tried to use componentDidUpdate() but then it triggers the focus again and again when I close the sideBar. I only want to focus only at first time when I load the page.
I am new at coding, please suggest something that can be done here.
Thanks in advance.
you have to create ref , then in your lifecycle method use that ref, you have forgotten to use current when you are using ref in lifecycle method, your code will be like this:
class GroupDetail extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount(){
this.ref.current.focus()
}
render(){
return(
<input type="text" ref={this.inputRef}/>
)
}
}
If you want to focus a single Input then you can simply do
<input type="text" autofocus>
If you just want to focus an element when it mounts (initially renders) a simple use of the autoFocus attribute will do.
<input type="text" autoFocus />
Or if you want to do it with componentDidMount and to control focus dynamically you can go with the below snippet
class App extends React.Component{
componentDidMount(){
this.nameInput.focus();
}
render() {
return(
<div>
<input defaultValue="Won't focus"/>
<input ref={(element) => { this.nameInput = element; }} defaultValue="will focus"/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

What are the differences between defaultValue and value in select?

I have two react components, parent and child. I'm passing a prop to a child component, and I want to use that prop to set the defaultValue on a select input. However, if that property changes, I'd like for the select default value to change as well.
When I set default value in select, I can choose one of the options that is a part of that selector. If I use value instead, the 'default' changes as the property updates, but I can't select any of the options.
class Selector extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<select defaultValue={this.props.value}>
<option>1</option>
<option>2</option>
</select>
)
}
}
I'd like for the value to change, and I realize that it is not re rendering even though the prop has changed. I'm looking for a work around.
I'm quoting:
The difference between the defaultValue and value property, is that
defaultValue contains the default value, while value contains the
current value after some changes have been made. If there are no
changes, defaultValue and value is the same.
The defaultValue property is useful when you want to find out whether
the contents of a text field have been changed.
What that actually means is that if you put defaultValue, this value will be initialized to the input and that's it, you can change value and the text will change.
But if you put value, you would need to change that value given to the input in the first place in order for input text to change.
Look at this example, all using the same state, but behaving differently.
// Example class component
class Thingy extends React.Component {
constructor(props) {
super(props);
this.state = { value: 'test' }
}
onChange(e) {
this.setState({ value: e.target.value });
}
render() {
return (
<div>
<div><b>default value</b> (you can edit without changing this.state.value)</div>
<input defaultValue={this.state.value}></input>
<div><b>value</b> (you can't edit because it does not change this.state.value)</div>
<input value={this.state.value}></input>
<div><b>value</b> (you can edit because it has onChange method attached that changes this.state.value) <br /> <b>NOTE:</b> this will also change second input since it has attached the same state with <b>value</b> property, but won't change first input becase same state was attached as <b>defaultValue</b></div>
<input value={this.state.value} onChange={e => this.onChange(e)}></input>
</div>
);
}
}
// Render it
ReactDOM.render(
<Thingy />,
document.body
);
div > div {
font-size: 16px;
}
input + div {
margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
When you don't have onChange handler you need to put your value as defaultValue, but in value when you have onChange handler.
You can do this,
class Selector extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: props.value
}
}
change = (event) =>{
this.setState({selected: event.target.value});
}
componentDidUpdate(prevProps, prevState) {
if (prevState.selected !== this.props.value) {
this.setState({selected: this.props.value})
}
}
render() {
return (
<select value={this.state.selected} onChange={this.change}>
<option>1</option>
<option>2</option>
</select>
)
}
}
defaultValue is selected value while very first time loading
and
value is selected value every time to change option value

office-ui-fabric-react / TextField input properties alternative to onChanged

I'm currently using the TextField from office UI fabric and using the onChanged property to assign my prop in react the value being entered similar to their GitHub example.
However, the event handler is called for each element being entered. How can I make a call to the event handler(this._onChange) only when the user finishes entering the entire text (eg on focus dismiss, etc)?
I'm guessing that would be more efficient than logging an event with each letter being entered.
New to react. Appreciate your help!
This is more of an in-general way React uses the input onChange event. With React, you want to keep the value of your input in state somewhere, whether that is component state or a global store like Redux. Your state and UI should always be in sync. Because of this, the onChange event fires for every character that is entered/removed so that you can update that state to reflect the new value. Inputs written this way are called Controlled Components and you can read more about them and see some examples at https://reactjs.org/docs/forms.html.
That being said, you can detect when the user leaves the input with the onBlur event, though I would not recommend using that to update the state with the value as you'll see that a Controlled Component will act read-only when you don't update the state in the onChange event. You will have to use an Uncontrolled Component, typically setting the initial value with defaultValue instead of value and making things more difficult for yourself.
// CORRECT IMPLEMENTATION
class ControlledForm extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: 'example'
};
this.handleNameChange = this.handleNameChange.bind(this);
}
handleNameChange(e) {
this.setState({
name: e.target.value
});
}
render() {
return (
<div>
<h1>Controlled Form</h1>
<input type="text" value={this.state.name} onChange={this.handleNameChange} />
<p>{this.state.name}</p>
</div>
);
}
}
// INPUT DOES NOT WORK
class BuggyUncontrolledForm extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: 'example'
};
}
render() {
return (
<div>
<h1>Buggy Uncontrolled Form</h1>
<input type="text" value={this.state.name} />
<p>{this.state.name}</p>
</div>
);
}
}
// NOT RECOMMENDED
class UncontrolledForm extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: 'example'
};
this.handleNameChange = this.handleNameChange.bind(this);
}
handleNameChange(e) {
this.setState({
name: e.target.value
});
}
render() {
return (
<div>
<h1>Uncontrolled Form</h1>
<input type="text" defaultValue={this.state.name} onBlur={this.handleNameChange} />
<p>{this.state.name}</p>
</div>
);
}
}
ReactDOM.render(
<div>
<ControlledForm />
<BuggyUncontrolledForm />
<UncontrolledForm />
</div>
, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
You may consider using React's onBlur prop which will be invoked when the input loses focus. Here is an example Codepen which window.alert's the <TextField> component's current value when it loses focus: https://codepen.io/kevintcoughlin/pen/zmdaJa?editors=1010.
Here is the code:
const {
Fabric,
TextField
} = window.Fabric;
class Content extends React.Component {
public render() {
return (
<Fabric>
<TextField onBlur={this.onBlur} />
</Fabric>
);
}
private onBlur(ev: React.FocusEvent<HTMLInputElement>) {
window.alert(ev.target.value);
}
}
ReactDOM.render(
<Content />,
document.getElementById('content')
);
I hope you find that helpful.
References
https://reactjs.org/docs/events.html#focus-events
You can keep your state and UI in sync but use things like your own deferred validation error-check functions to check if the value is good/bad AND/or if you want to do something like logging based on the value only after a certain amount of time passes. Some examples from this page copied below for quick reference - you can do whatever you want in your "_getErrorMessage" function (https://github.com/OfficeDev/office-ui-fabric-react/blob/master/packages/office-ui-fabric-react/src/components/TextField/examples/TextField.ErrorMessage.Example.tsx):
<TextField
label="Deferred string-based validation"
placeholder="Validates after user stops typing for 2 seconds"
onGetErrorMessage={this._getErrorMessage}
deferredValidationTime={2000}
/>
<TextField
label="Validates only on focus and blur"
placeholder="Validates only on input focus and blur"
onGetErrorMessage={this._getErrorMessage}
validateOnFocusIn
validateOnFocusOut
/>

React form input won't let me change value

I have a component in a React class in my Laravel project which is a simple form with one input field. It houses a phone number which I have retrieved from the database and passed back through the reducer and into the component as a prop. Using this, I have passed it through to the module as a prop which then populates the field with the currently saved value:
<OutOfOfficeContactNumberForm
show={props.showOutOfOffice}
value={props.outOfOfficeNumber}
handleChange={console.log("changed")}
/>
I have a handleChange on here which is supposed to fire a console log, but it only ever displays on page load. Here is my form module class:
class OutOfOfficeContactNumberForm extends React.Component {
render() {
const { show, value, handleChange } = this.props;
if(!show) return null;
return (
<div>
<p>
Please supply an Out of Office contact number to continue.
</p>
<InputGroup layout="inline">
<Label layout="inline" required={true}>Out of Office Contact Number</Label>
<Input onChange={handleChange} value={value} layout="inline" id="out-of-office-number" name="out_of_office_contact_number" />
</InputGroup>
</div>
);
}
}
export default (CSSModules(OutOfOfficeContactNumberForm, style));
The form is embedded in my parent component, as follows:
return (
<SectionCategoriesSettingsForm
isSubmitting={this.state.isSubmitting}
page={this.props.page}
show={this.props.show}
categories={this.props.categories}
submitSectionCategoriesSettings={this._submit.bind(this, 'add')}
updateSelectedCategories={this._updateSelectedCategories.bind(this)}
selectedCategoryIds={this.state.selectedCategoryIds}
storedUserCategories={this.props.selectedCategories}
outOfOfficeNumber={this.state.outOfOfficeNumber}
onUpdateContactNumber={this._updateContactNumber.bind(this)}
/>
);
In my componentWillReceiveProps() function, I set the state as follows:
if (nextProps.selectedCategories && nextProps.selectedCategories.length > 0) {
this.setState({
outOfOfficeNumber: nextProps.outOfOfficeNumber,
selectedCategoryIds: nextProps.selectedCategories.map(c => c.id)
});
}
I'm pretty sure the reason it's not changing is because it's pre-loaded from the state which doesn't change - but if I cannot edit the field how can I get it to register a change?
EDIT: Just to clarify there are also checkboxes in this form for the user to change their preferences, and the data retrieved for them is set the same way but I am able to check and uncheck those no problem
Changes:
1- onChange expect a function and you are assigning a value that's why, put the console statement inside a function and pass that function toOutOfOfficeContactNumberForm component , like this:
handleChange={() => console.log("changed")}
2- You are using controlled component (using the value property), so you need to update the value inside onChange function otherwise it will not allow you to change means input values will not be not reflect in ui.
Check example:
class App extends React.Component {
state = {
input1: '',
input2: '',
}
onChange = (e) => this.setState({ input2: e.target.value })
render() {
return(
<div>
Without updating value inside onChange
<input value={this.state.input1} onChange={console.log('value')} />
<br />
Updating value in onChange
<input value={this.state.input2} onChange={this.onChange} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />
I think the best way is when you get data from database put it to state and pass the state to input and remember if you want to see input changes in typing, use a function to handle the change and that function should change state value.
class payloadcontainer extends Component {
constructor(props) {
super(props)
this.state = {
number:1
}
}
render() {
return (
<div>
<input value={this.state.number} onChange={(e)=>this.setState({number:e.target.value})}></input>
<button onClick={()=>this.props.buyCake(this.state.number)}><h3>buy {this.state.number} cake </h3></button>
</div>
)
}
}

disable semantic Button in react

how to dynamically set semantic Button to disabled in react:
<Button disabled>click here<Button>
i tryed to set it with state but it gave me an error
this.setState({d:'disabled'})
return (<Button {this.state.d} >click here<Button>)
It's impossible to tell how your Button is handling disabled under the hood but assuming it´s working like the JSX element .
First, JSX elements are just functions that takes a set of arguments (props). So you still need to give it a disabled:boolean. As you can see below you need to provide a name and a value. Your attempt at {this.state.d} gives just the value true/false. Please look at the snippet below for how you can do it. Either explicit or by giving it a named variable or finally by spreading out an object.
class HelloWorldComponent extends React.Component {
constructor(){
super();
this.state = {
disabled: true
}
}
render() {
const disabled = this.state.disabled; //Pull out the value to a named variable
return (
<div>
<button disabled={false}>Button1</button>
<button disabled>Button2</button>
<button {...this.state}>Button3</button>
</div>
);
}
}
React.render(
<HelloWorldComponent/>,
document.getElementById('react_example')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="react_example"></div>

Resources