Click to Enable TextField React - reactjs

I am displaying tabular data and each cell displays data using a TextField of Material UI (like input field). I want to show all of these TextFields as disabled at first, and enable any of them if they are clicked on. So user would click on the TextField and field would become available to alter. How can I do that?
Setting the state for field
state = {
button: false,
}
I have the TextField like below:
<TextField
disabled={this.state.button}
onClick={this.fieldActivate}
name="abc"
Activating field
fieldActivate(event) {
this.setState({
button: true
})
}

onClick and disabled
They don"t work together since disabled elements are not clickable. However, you could use something like onMouseOver.
Callback and Scope
If you want to define a function for an Event which uses this keyword, you need to either bind this or call the function from an anonymous function.
Finding the target
Since you only want one field to be enabled, you need to identify it somehow. Give them keys/ids.
Example
class MyComponent extends React.Component {
state = {
enabled: -1
}
handleMouseOver(id) {
this.setState({
enabled: id
});
}
render() {
let inputs = [];
for (let i=0; i<=20; i++) {
inputs.push({ id: i, placeholder: 'Input ' + i });
}
return (
<div>
{inputs.map((input) => {
return(
<input
disabled={this.state.enabled !== input.id}
type='text'
placeholder={input.placeholder}
onMouseOver={(e) => {
this.handleMouseOver(input.id);
}}
/>
);
})}
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('app')
);
input:disabled{
background: #ccc;
}
<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>

state = { currentFocusElement: '' }
...
<TextField
disabled={this.state.currentFocusElement !== 'name'}
onFocus={() => this.setState({ currentFocusElement: 'name' })}
The idea is force a re-render when onfocus, and change the disabled value

Related

How to change style of input tag based on checkbox?

I have input form and input tag as a button.
Before I was able to make a button which changed styling according to clicking on it but now i try to make this input gray until user check the checkbox. I tried to use <Show> and when property but i cant use when on <Show> tag. Then I tried to use onChange property and it seem to not give me any errors. I just don't understand how can I change styling inside class=" and then connect it to checkbox function? My checkbox is made by using createSignal
Any ideas?
<input
onChange={functionForStyling}
name="submit"
type={"submit"}
value={"Sign up"}
class=""
/>
Assigning a class to a checkbox element is not different than assigning it to any html element.
Here is how you can assign a class to an html element conditionally.
import { createSignal, JSX } from 'solid-js';
import { render } from 'solid-js/web';
const App = () => {
const [isChecked, setIsChecked] = createSignal(true);
const toggle = () => setIsChecked(c => !c);
const handleChange: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
setIsChecked(event.currentTarget.checked);
};
return (
<div>
<style>{`
input.checked {
transform: rotate(45deg);
}
input.unchecked {
transform: rotate(45deg);
}
`}</style>
<input
type='checkbox'
class={isChecked() ? 'checked' : 'unchecked'}
checked={isChecked()}
onChange={handleChange}
/>
{` `}
<button onclick={toggle}>Toggle</button>
</div>
);
};
render(() => <App />, document.body);
https://playground.solidjs.com/anonymous/163ffec6-1293-4702-9ef6-0425461328c3
Please keep in mind that styling a checkbox is not that straightforward. You need to use pseudo selectors etc.

How to allow user formatting in React app?

I have a React app where a user can type something into textbox, click 'submit' and then the text appears somewhere.
I want to add functionality which will allow the user to format the text. Just like you can do here on SE when asking questions. For example I want the below input to be shown as bold.
<b>bold</b>
How can I achieve this? Or where to look for this kind of thing?
If you want to enable the same functionality you get in stack overflow, then I think the one way to achieve this would be allowing the user to input markdown and converting that to HTML. This is a library that could help with that: marked
Freecodecamp has a markdown previewer as one of their projects, so if you want to check out some examples, you could probably find hundreds of different implementations: https://www.freecodecamp.org/forum/t/build-a-markdown-previewer/198715
Yes, this can be done using state, as well as a checkbox toggle to determine whether or not the text should be bold or not.
handleChange will update the input. handleFormatChange will update whether or not you should use bold text or not. In the render, a conditional can be implemented to determine when to render what format.
class Formatter extends React.Component {
state = {
format: false,
input: ""
}
handleChange = () => {
this.setState({
input: event.target.value
})
}
handleFormatChange = () => {
this.setState({
format: !this.state.format
})
}
render() {
var input = this.state.format
? <b> {this.state.input} </b>
: <p> {this.state.input} </p>
return (
<div>
Bold <input type="checkbox"
onChange = {
this.handleFormatChange
}
/>
<br />
<input value={this.state.input}
onChange = {this.handleChange}
/>
<br/>
{input}
</div>
);
}
}
ReactDOM.render( <
Formatter / > ,
document.getElementById('root')
);
p {
margin-top: 0px;
}
<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="root">
<!-- This element's contents will be replaced with your component. -->
</div>

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>
)
}
}

Bootstrap Checkbox Not Toggling

I am using a Bootstrap checkbox and a regular one. Why is the Bootstrap Checkbox failing to toggle, while the regular input field succeeds to toggle?
onChange = (evt) => {
const target = evt.target;
const name = target.name;
const value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
[name]: value
});
this.props.onChange({ name, value });
};
<input
name="unlimited"
type="checkbox"
checked={this.state.unlimited}
onChange={this.onChange} />
<Checkbox
name="unlimited"
onChange={this.onChange}
checked={this.state.unlimited}
>
UNLIMITED {this.state.unlimited.toString()}
</Checkbox>
EDIT
I made a bunch of mistakes when I originally posted code. Above is the corrected code.
EDIT
I am convinced this is a bug because Bootstrap JS library is interfering, see here.
You are passing to checked prop of the Checkbox a value from the parent via props. Are you sure you update the new state in the parent and passing a new prop again?
Here is an example using your code:
const { Checkbox } = ReactBootstrap;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
unlimited: false
};
}
onChange = (evt) => {
const target = evt.target;
const name = target.name;
const value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
[name]: value
});
};
render() {
const { unlimited } = this.state;
return (
<div>
<input
name="unlimited"
type="checkbox"
checked={this.state.unlimited}
onChange={this.onChange} />
<Checkbox
name="unlimited"
onChange={this.onChange}
checked={this.state.unlimited}
>
UNLIMITED {this.state.unlimited.toString()}
</Checkbox>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/0.31.3/react-bootstrap.min.js"></script>
<div id="root"></div>
Edit
Any experience in overriding the bootstrap.js? it is on the global
template page of our app (PHP smarty)
I'm not a PHP expert but i guess you can conditionally render the script tag of bootstrap.js, So when you redirected to the page that use your react application just don't render the <script> tag.
you have a controlled input - see https://reactjs.org/docs/forms.html#controlled-components
in this case, the checked is bound to your parent component's prop fields={unlimited}
you tells your parent via onChange={} that there's a new name and value - it will be up to it to setState() in a way that passes a new fields.unlimited
Eg, your stateful parent can be:
class Foo extends Component {
state = {
unlimited: false
}
onChange = (name, value) => this.setState({[name]: value})
render(){
return <MyOtherComponent fields={this.state} onChange={this.onChange} />
}
}
if your component is stateful itself (looking at your handleChange), then you can convert to uncontrolled (https://reactjs.org/docs/uncontrolled-components.html) or bind to your local state if you sync it from props on mount and when it gets props.

How do I reset the defaultValue for a React input

I have a set of React input elements that have a defaultValue set. The values are updated with an onBlur event.
I also have another action on the page that updates all values in these input elements. Is there a way to force react to render the new defaulValues when this happens?
I can't easily use onChange since it would trigger a premature rerender (The inputs contain a display order value and a premature rerender would move them).
I could create a duplicate state, one for the real values that is only updated with onBlur and one to update the value in the input element while it is being edited. This would be far from ideal. It would be so much simpler to just reset the default values.
As mentioned in https://stackoverflow.com/a/21750576/275501, you can assign a key to the outer element of your rendered component, controlled by state. This means you have a "switch" to completely reset the component because React considers a new key to indicate an entirely new element.
e.g.
class MyComponent extends React.Component {
constructor() {
super();
this.state = {
key: Date.now(),
counter: 0
};
}
updateCounter() {
this.setState( { counter: this.state.counter + 1 } );
}
updateCounterAndReset() {
this.updateCounter();
this.setState( { key: Date.now() } );
}
render() { return (
<div key={this.state.key}>
<p>
Input with default value:
<input type="text" defaultValue={Date.now()} />
</p>
<p>
Counter: {this.state.counter}
<button onClick={this.updateCounter.bind( this )}>Update counter</button>
<button onClick={this.updateCounterAndReset.bind( this )}>Update counter AND reset component</button>
</p>
</div>
); }
}
ReactDOM.render( <MyComponent />, document.querySelector( "#container" ) );
<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="container" />
I've solved this by using both onBlur and onChange and only keeping track of the currently active input element in the state.
If there is a way to reset the module so that it re-displays the new default values then I'll mark that as correct.
state = {
inFocusIndex: null,
inFocusDisplayOrder: 0,
};
onOrderBlur() {
const productRow = this.props.products[this.state.inFocusIndex];
const oldDisplayORder = productRow.displayOrder;
// This can change all the display order values in the products array
this.props.updateDisplayOrder(
this.props.groupId,
productRow.productGroupLinkId,
oldDisplayORder,
this.state.inFocusDisplayOrder
);
this.setState({ inFocusIndex: null });
}
onOrderChanged(index, event) {
this.setState({
inFocusIndex: index,
inFocusDisplayOrder: event.target.value,
});
}
In the render function:
{this.props.products.map((row, index) => {
return (
<input
type="text"
value={index === this.state.inFocusIndex ? this.state.inFocusDisplayOrder : row.displayOrder}
className={styles.displayOrder}
onChange={this.onOrderChanged.bind(this, index)}
onBlur={this.onOrderBlur.bind(this)} />
);
})}

Resources