Firing a Method Directly from Input in React - html

Is there a way to dispatch an action directly from an input tag?
<input
className="text"
required
onChange={this.props.updateInput.bind(this,"title",e.target.value)}
value={this.props.title}
/>
I'm having an issue where e.target.value is no recognized.

You can do it by creating a new inlined arrow function that passes along the value from the event.
<input
className="text"
required
onChange={e => this.props.updateInput("title", e.target.value)}
value={this.props.title}
/>

If you use #Tholle's advise then you should use updateInput function like that:
updateInput(title, value) {
console.log( title, value );
}
I don't know why you need "title" string as a variable there, but if your intent is changing a title state where resides in a parent from your child component here is an example:
class App extends React.Component {
state = {
title: "",
}
updateInput = title => {
this.setState( { title });
}
render() {
return (
<div>
<Input title={this.state.title} onChange={this.updateInput} />
<br />
Title is: {this.state.title}
</div>
);
}
}
const Input = (props) => {
const handleInput = e =>
props.onChange(e.target.value)
return (
<input
className="text"
required
onChange={handleInput}
value={props.title}
/>
);
}
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"></div>

Related

Specify focus on element which has active class name

I´d like to help with this problem:
I´ve got this example code below:
import React, { useRef, useEffect } from "react";
function App() {
const inputRef = useRef(null);
useEffect(() => {
const testElement = document.querySelectorAll(".active");
testElement.length > 0 && inputRef.current.focus();
}, []);
return (
<div style={{width: 200, height: 190, display: "flex", flexDirection: "column", justifyContent: "space-between"}}>
<input id={1} type="text" ref={inputRef} />
<input id={2} type="text" ref={inputRef} />
<input id={3} className={"active"} type="text" ref={inputRef} />
<input id={4} type="text" ref={inputRef} />
</div>
);
}
export default App;
And I like to know, how to focus on concrete element which has some class name. In my case it´s "active" class name on input field with id "3". But the problem is, that it´s not working and focused is the input element with id "4".
Thanky you.
Ideally in React, the class .active should be controlled by changing the state/properties. In this case, the action that changes the state (click for example), or the state itself can also control the focus (see 3rd example). In addition, we don't want to access the DOM directly.
In your case, the elements are sharing the same ref, and replace each other when render. That's why the last item is the only one that gets the focus.
To get what you want with refs, inputRef should be an array, and each input should use a function ref to add itself to the array.
Now you can scan the items in useEffect, find one that has the .active class and focus it.
const { useRef, useEffect } = React;
function App() {
const inputRef = useRef([]);
useEffect(() => {
for(const r of inputRef.current) {
if(r.classList.contains('active')) {
r.focus();
return;
}
}
}, []);
const addRef = r => inputRef.current.push(r)
return (
<div style={{width: 200, height: 190, display: "flex", flexDirection: "column", justifyContent: "space-between"}}>
<input id={1} type="text" ref={addRef} />
<input id={2} type="text" ref={addRef} />
<input id={3} className={"active"} type="text" ref={addRef} />
<input id={4} type="text" ref={addRef} />
</div>
);
};
ReactDOM.render(
<App />,
root
);
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
However, since you are already access the DOM anyway, you can use document.querySelector() directly. This is still not the React way, but at least it's less cumbersome (you don't need refs):
const { useEffect } = React;
function App() {
useEffect(() => {
const active = document.querySelector('.active');
if(active) active.focus();
}, []);
return (
<div style={{width: 200, height: 190, display: "flex", flexDirection: "column", justifyContent: "space-between"}}>
<input id={1} type="text" />
<input id={2} type="text" />
<input id={3} className={"active"} type="text" />
<input id={4} type="text" />
</div>
);
};
ReactDOM.render(
<App />,
root
);
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
If you work with a model passed via state/props (props in this case), you can use the state/properties to control the focus (and the class) - see comments in the code:
const { useRef, useEffect } = React;
// Each item renders it's own input, and focuses the item if the selected prop is true
const Item = ({ selected }) => {
const inputRef = useRef(null);
useEffect(() => {
if(selected) inputRef.current.focus();
}, [selected]);
return (
<input className={selected ? 'active' : ''} type="text" ref={inputRef} />
);
};
// App renders a list of items
const App = ({ items }) => (
<div style={{width: 200, height: 190, display: "flex", flexDirection: "column", justifyContent: "space-between"}}>
{items.map(item => (
<Item key={item.id} {...item} />
))}
</div>
);
const items = [{ id: 1 }, { id: 2 }, { id: 3, selected: true }, { id: 4 }];
ReactDOM.render(
<App items={items} />,
root
);
.active {
outline: 1px solid red;
}
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>

How to pass a React component as an attribute to an HTML input

I would like to pass a React component as attribute to an html input.
class Test extends React.Component {
render() {
return "test";
}
}
function App() {
return (
<input type="text" value={<Test />} />
)
}
The problem here is that input is showing [object Object] where I would expect test
You can find that working code at https://codesandbox.io/s/modern-dawn-5ro04
Any idea how to display the rendered value in the html attribute ?
Unfortunately it is not possible to pass a React component inside the vanilla html components because there is an interface expects string only as a value of value attribute.
Just use a normal function instead of a react component. Assuming you're just trying to pass a string into the value of the input?
function test() {
//Insert logic here
return updated logic;
}
function App() {
return (
<input type="text" value={test()} />
);
}
Alternatively you could just pass an arrow function into the value:
'test'} />
But I'm assuming you want to do some logic in the test function so that probably wouldn't work.
You are returning a container instead create a function for value.
import React from "react";
import ReactDOM from "react-dom";
class Test extends React.Component {
render() {
return "test";
}
}
function AnotherComponent({ v }) {
return <div>AnotherComponent : {v}</div>;
}
function App() {
const valueField = () => {
return "test";
};
return (
<div>
<h1>Simple Test tag</h1>
<Test />
<h1>Test tag sent as props to another react component</h1>
<AnotherComponent v={<Test />} />
<h1>Test tag sent as attribute to a input type=text</h1>
<h2>Expected output :</h2>
<input type="text" value="test" />
<h2>My problem :</h2>
<input type="text" value={valueField()} />
<h2>Solution ?</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Passing a html value as a parameter in react

I need to pass a html value as a parameter for my function like so:
<input type ="text" placeholder="Smart Contract Bytecode" name="name" id ="scbytecode"className="nice-textbox"/>
<button id="button" onClick={parseAddress("document.getElementById('smartcontract').value)"}>Submit!</button>
but Im getting an error:
TypeError: Cannot read property 'value' of null
here is the Full code.
Added this to give a better impression of whats going on cause the fixes below don't seem to fix it all. Any help is welcomed.
class App extends Component {
parseAddress(_smartcontract){
var contractObj = new ethweb3.eth.Contract(ERC20ABI, document.getElementById('smartcontract').value);
contractObj.getPastEvents(
'Transfer' || 'allEvents',
{
fromBlock: 0,
toBlock: 'latest'
},
function(err,res){
console.log(err,res);
//examples to access the data returned
console.log(res.length);
document.getElementById("totalAddresses").innerHTML = res.length;
document.getElementById("sampleAddress").innerHTML = res[0].returnValues.from;
document.getElementById("sampleAmount").innerHTML = res[0].returnValues.value;
}
);
}
deploSC = async () => {
const accounts = await goweb3.eth.getAccounts();
//const code = ethweb3.eth.getCode(document.getElementById('smartcontract').value); Not working
console.log(code);
goweb3.eth.sendTransaction({
from: accounts[0],
data: document.getElementById('scbytecode').value
}, function(error, hash){
console.log(error,hash);
});
}
render() {
return (
<div className="App">
<header className="App-header">
<p>
Enter the smart contract address:
<input type="text" name="name" id="smartcontract" className="nice-textbox"/>
<input type ="text" placeholder="Sc bytecode" name="name" id ="scbytecode"className="nice-textbox"/>
<button id="button" onClick={this.parseAddress}>Submit!</button>
<button onClick={this.deploSC}> Deploy Sc</button>
</p>
<p id="totalAddresses">0</p>
<p id="sampleAddress">0</p>
<p id="sampleAmount">0</p>
</header>
</div>
);
}
}
export default App;
There is a better way to do this in React using state and not directly accessing the DOM which should be avoided.
Store the value of an input in the component's state, then give it to the button's onClick event handler via this.state.inputVal.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
inputVal: ''
};
}
inputChanged = (e) => {
this.setState({ inputVal: e.target.value });
}
render() {
return (
<div>
<input type ="text" placeholder="Smart Contract Bytecode" name="name" id ="scbytecode" className="nice-textbox" onChange={this.inputChanged}/>
<button id="button" onClick={() => { console.log(this.state.inputVal); }}>Submit!</button>
</div>
);
}
}
// Render it
ReactDOM.render(
<App/>,
document.getElementById("react")
);
<div id="react"></div>
<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>
I think there is mismatch in id.
line 1 you gave "scbytecode"
line 2 you are trying access by id "smartcontract" which is not present, so you are seeing null

React-Redux is not rendering data correctly inside input/textarea box

I have the example below where (1) and (2) would display the value of "Some Text" instead of Data.preview but (3) would show up Data.preview value just fine. I understand that case (1) - based on this article (ReactJS component not rendering textarea with state variable) wouldn't work for react but why does case (2) return "Some Text" (I also tried value=) instead of Data.preview value like case (3). I do not want it to be a placeholder so it would be editable. Thanks
render(){
const { Data } = this.props
return (
{Data.preview} {*/this would return the value correctly*/}
(1) <textarea className="form-control" maxLength="50" rows="3">{ Data.preview || "Some Text" }</textarea>
(2) <textarea className="form-control" maxLength="50" rows="3" defaultValue={ Data.preview || "Some Text"}></textarea> {*/or use value = {}, either would return "Some Text" */}
(3) <textarea className="form-control" placeholder={Data.preview || "Some Text"} maxLength="50" rows="3"></textarea>{*/ this would return Data.preview value */}
)
}
The textarea can take the value property for showing its current value, and then use the onChange handler to update that value.
In this sample I added both the one with no value yet, and the one which has a default value.
An important note would be that a value cannot be null; it has to be either undefined or empty.
The answer here doesn't really involve redux, but rather a component state for editing the value. I hope this helps enough to use it, applying it to your code.
const { Component } = React;
class DataEntrySample extends Component {
constructor( props ) {
super();
this.state = {
data: props.value
};
this.updateData = this.updateData.bind(this);
}
updateData(e) {
this.setState({ data: e.target.value });
console.log('changed to :' + e.target.value );
}
render() {
return (
<textarea
value={this.state.data}
onChange={this.updateData}
placeholder={this.state.data || 'Enter your data'}>
</textarea>
);
}
}
const target = document.querySelector('#container');
ReactDOM.render( <div><DataEntrySample /><DataEntrySample value="Some text" /></div>, target );
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<div id="container"></div>
If you really want to do it through defaultValue, you have a chance to do that as well (as long as you define an onChange handler that updates the value somewhere).
There is rather a caveat, namely, it will not update any changes from outside of it's view, unless it can define that it has really changed, and with defaultValue. So the following example would work, changing the props from outside would not work.
const { Component } = React;
class DataEntrySample extends Component {
constructor( props ) {
super();
this.state = {
data: props.value
};
this.updateData = this.updateData.bind(this);
}
updateData(e) {
this.setState({ data: e.target.value });
console.log('changed to :' + e.target.value );
}
render() {
return (
<textarea
onChange={this.updateData}
defaultValue={this.state.data || 'Enter your data'}>
</textarea>
);
}
}
class ParentEntry extends Component {
constructor() {
super();
this.updateProps = this.updateProps.bind(this);
this.state = {
value: 'initial text'
};
}
updateProps( value ) {
this.setState({ value });
}
render() {
const { value } = this.state;
console.log( 'render' );
return (
<div>
<h1>With default value</h1>
<DataEntrySample value={value} />
<br />
<button onClick={()=>this.updateProps('empty text')} type="button">
Will set text to empty text
</button>
</div>
);
}
}
const target = document.querySelector('#container');
ReactDOM.render( <ParentEntry />, target );
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<div id="container"></div>
You need to learn a bit more about controller components https://reactjs.org/docs/forms.html
If you then decide that you really need uncontrolled components: https://reactjs.org/docs/uncontrolled-components.html

How to manually trigger click event in ReactJS?

How can I manually trigger a click event in ReactJS?
When a user clicks on element1, I want to automatically trigger a click on the input tag.
<div className="div-margins logoContainer">
<div id="element1" className="content" onClick={this.uploadLogoIcon}>
<div className="logoBlank" />
</div>
<input accept="image/*" type="file" className="hide"/>
</div>
You could use the ref prop to acquire a reference to the underlying HTMLInputElement object through a callback, store the reference as a class property, then use that reference to later trigger a click from your event handlers using the HTMLElement.click method.
In your render method:
<input ref={input => this.inputElement = input} ... />
In your event handler:
this.inputElement.click();
Full example:
class MyComponent extends React.Component {
render() {
return (
<div onClick={this.handleClick}>
<input ref={input => this.inputElement = input} />
</div>
);
}
handleClick = (e) => {
this.inputElement.click();
}
}
Note the ES6 arrow function that provides the correct lexical scope for this in the callback. Also note, that the object you acquire this way is an object akin to what you would acquire using document.getElementById, i.e. the actual DOM-node.
Here is the Hooks solution:
import React, {useRef} from 'react';
const MyComponent = () => {
const myRefname= useRef(null);
const handleClick = () => {
myRefname.current.focus();
}
return (
<div onClick={handleClick}>
<input ref={myRefname}/>
</div>
);
}
Got the following to work May 2018 with ES6
React Docs as a reference: https://reactjs.org/docs/refs-and-the-dom.html
import React, { Component } from "react";
class AddImage extends Component {
constructor(props) {
super(props);
this.fileUpload = React.createRef();
this.showFileUpload = this.showFileUpload.bind(this);
}
showFileUpload() {
this.fileUpload.current.click();
}
render() {
return (
<div className="AddImage">
<input
type="file"
id="my_file"
style={{ display: "none" }}
ref={this.fileUpload}
/>
<input
type="image"
src="http://www.graphicssimplified.com/wp-content/uploads/2015/04/upload-cloud.png"
width="30px"
onClick={this.showFileUpload}
/>
</div>
);
}
}
export default AddImage;
You can use ref callback which will return the node. Call click() on that node to do a programmatic click.
Getting the div node
clickDiv(el) {
el.click()
}
Setting a ref to the div node
<div
id="element1"
className="content"
ref={this.clickDiv}
onClick={this.uploadLogoIcon}
>
Check the fiddle
https://jsfiddle.net/pranesh_ravi/5skk51ap/1/
Hope it helps!
In a functional component this principle also works, it's just a slightly different syntax and way of thinking.
const UploadsWindow = () => {
// will hold a reference for our real input file
let inputFile = '';
// function to trigger our input file click
const uploadClick = e => {
e.preventDefault();
inputFile.click();
return false;
};
return (
<>
<input
type="file"
name="fileUpload"
ref={input => {
// assigns a reference so we can trigger it later
inputFile = input;
}}
multiple
/>
<a href="#" className="btn" onClick={uploadClick}>
Add or Drag Attachments Here
</a>
</>
)
}
Riffing on Aaron Hakala's answer with useRef inspired by this answer https://stackoverflow.com/a/54316368/3893510
const myRef = useRef(null);
const clickElement = (ref) => {
ref.current.dispatchEvent(
new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
buttons: 1,
}),
);
};
And your JSX:
<button onClick={() => clickElement(myRef)}>Click<button/>
<input ref={myRef}>
Using React Hooks and the useRef hook.
import React, { useRef } from 'react';
const MyComponent = () => {
const myInput = useRef(null);
const clickElement = () => {
// To simulate a user focusing an input you should use the
// built in .focus() method.
myInput.current?.focus();
// To simulate a click on a button you can use the .click()
// method.
// myInput.current?.click();
}
return (
<div>
<button onClick={clickElement}>
Trigger click inside input
</button>
<input ref={myInput} />
</div>
);
}
this.buttonRef.current.click();
Try this and let me know if it does not work on your end:
<input type="checkbox" name='agree' ref={input => this.inputElement = input}/>
<div onClick={() => this.inputElement.click()}>Click</div>
Clicking on the div should simulate a click on the input element
let timer;
let isDoubleClick = false;
const handleClick = () => {
if(!isDoubleClick) {
isDoubleClick = true;
timer = setTimeout(() => {
isDoubleClick = false;
props.onClick();
}, 200);
} else {
clearTimeout(timer);
props.onDoubleClick();
}
}
return <div onClick={handleClick}></div>
for typescript you could use this code to avoid getting type error
import React, { useRef } from 'react';
const MyComponent = () => {
const fileRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
fileRef.current?.focus();
}
return (
<div>
<button onClick={handleClick}>
Trigger click inside input
</button>
<input ref={fileRef} />
</div>
);
}
If it doesn't work in the latest version of reactjs, try using innerRef
class MyComponent extends React.Component {
render() {
return (
<div onClick={this.handleClick}>
<input innerRef={input => this.inputElement = input} />
</div>
);
}
handleClick = (e) => {
this.inputElement.click();
}
}
imagePicker(){
this.refs.fileUploader.click();
this.setState({
imagePicker: true
})
}
<div onClick={this.imagePicker.bind(this)} >
<input type='file' style={{display: 'none'}} ref="fileUploader" onChange={this.imageOnChange} />
</div>
This work for me
How about just plain old js ?
example:
autoClick = () => {
if (something === something) {
var link = document.getElementById('dashboard-link');
link.click();
}
};
......
var clickIt = this.autoClick();
return (
<div>
<Link id="dashboard-link" to={'/dashboard'}>Dashboard</Link>
</div>
);