Send an event from html form to a jsx component - javascript

I am new to React,
My question is:
I have a button (Btn) in html form and a react input text (TXT) component; I want to make the button clicked on the "oninput" event of the txt.
this is the component jsx file:
(function(app){
function component(){
var Date = React.createClass({
getValue: function() {
var el = $(this.getDOMNode());
var input = el[0].childNodes[1].childNodes[0];
return $(input).val();
},
componentDidMount: function() {
var el = $(this.getDOMNode());
var element = el[0].childNodes[1];
$(element).datetimepicker({
autoclose: true,
format: 'yyyy-mm-dd',
startView: 'decade',
minView: 'month',
isRTL: false,
//pickTime: false,
pickerPosition:"bottom-right"
});
},
render: function() {
return (<div className="form-group" style={{display: '-webkit-box'}}>
<label>{this.props.title}</label>
<div className="input-group date ">
<input type="text" name={this.props.name} style={{paddingRight: 0,
fontSize: 12}} readOnly className="form-control" className={this.props.class}/>
<span className="input-group-btn">
<button className="btn default date-set" type="button"><i className="fa fa-calendar"></i></button>
</span>
</div>
</div>);
}
});
function create(elementId,props){
return React.render(<Date {...props} />, document.getElementById(elementId));
}
return {
create:create
};
}
app.component('dateComponent',component);
})(beirutHubBaseApp);
The button is in html file; this button is a search button made by jquery datatable so it has to be in the datatable.
this is the controller:
jd = dateComponent.create('jd',
{
title:"",
name:"filter_joinDate",
class:"form-control form-filter datepicker"
});
So how to make this event?

First of all, instead of having
var el = $(this.getDOMNode());
var element = el[0].childNodes[1];
You should use refs, this is what they are for, see http://facebook.github.io/react/docs/more-about-refs.html .
Second, your getValue function is not at all in the spirit of React. Either you also use refs and then you can get your input value through this.refs.input.value or you use a state to store the value.
Concerning your problem :
if you want to react to the click on the button to trigger something in the text field, you should add the listener in the componentDidMount, like this :
componentDidMount:
var c = this
$("#mybutton").click(function(e) {
// do something here, with c instead of this to refer to the component
})
Do not forget to also implement the componentWillUnmount to clear the listener.
If you want to trigger something in the button in reaction to an input (which I believe is what you are looking for), you should add a listener to the input like this onInput={this.handleInput} and have a handleInput this way :
handleInput:
handleInput: function() {
$("#mybutton").doSomethingWithJquery()
},

Related

react - setting input prop based on input name

I have a checkbox input:
import { Checkbox } from 'semantic-ui-react';
<Checkbox
checked={false}
ref={id}
/>
Now I would like to write a function that set this checkbox's checked to true (the onClick function goes on another React element, not the checkbox itself):
onClick: (id) => {
//Find the correct checkbox, set the prop
this.refs[id].checked = true;
}
But I have no idea how to do it (the above code does nothing). How do I find react components based on a certain prop?
Maintain a state object that has mapping of id to checkbox state and then onClick based on the id change the state
this.state = {
checked: {'12': true. '23':false}
}
<Checkbox
checked={this.state.checked[id]}
/>
If you want to toggle
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = !this.state.checked[id];
this.setState({checked})
}
If you only want to set
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = true;
this.setState({checked})
}
You have to add an onClick attribute in the Checkbox and the funciton name.
Inside the on click function you should get as parameter the event
and check the evet.target.checked
which is the checkbox's attribute to show clicked status.
You don't need to use refs if its all in the same component.
Let me know if you have trouble
You could do something like:
<Checkbox
checked={false}
ref={id}
onClick={() => { this.onClick(id); }}
/>
Not sure if this Checkbox is rendered in the same component tho, so the reference to this might be wrong.
onClick: (id) => {
this.refs[id].checked = true;
}

React <a> tag and button onClick propagation

I want to create a React component with a render method that has an <a> tag that wraps an entire "box", if you will, which redirects to another page when clicked. Within said box there is a <button> that can be clicked that activates an event that changes state.
What I want to be able to do is click the <button> and trigger the event without the redirect from the <a> tag occurring.
Tried some ideas with stopPropagation() but no luck :/ I don't want to move the button outside of the <a> tag either so not sure where to go from here.
It seems like it should be something simple but I just can't figure it out. Thanks!
the render method looks like this:
render(){
return(
<div>
<a href="http://www.google.com">
<div className="box">
<h2 className="title">Random Title</h2>
<button onClick={this.handleClick}> Like </button>
</div>
</a>
</div>
)
}
handleClick() would look something like this:
handleClick = () => {
if (this.state.liked) {
console.log("disliking")
} else {
console.log("liking")
}
this.setState({ liked: !this.state.liked})
}
you can achieve this with a simple trick. see what I did -
replace the anchor with a div and place a click handler
add a flag (clicked) with in the component and ignore in div click handler if it's a button click
reset the flag
update - check out this js fiddle :
https://jsfiddle.net/rabinarayanb/pvx2n3x3/
note - I have used es5 syntax. you can convert to es6
(function() {
var BoxSetup = React.createClass({
clicked : "",
getInitialState : function () {
return { clickCount : 0};
},
handleDivClick : function (event) {
if (this.clicked !== "Button") {
window.location.href = "http://www.google.com";
}
// reset
this.clicked = "";
},
handleButtonClick : function (event) {
this.clicked = "Button"
this.setState({
clickCount : ++this.state.clickCount
});
},
render : function () {
return (
<div>
<div onClick={this.handleDivClick} style={ { }}>
<div style={ { width : "100px", height : "100px", border : "1px solid red" } }>
<h2 className="title">{ this.state.clickCount }</h2>
<button onClick={this.handleButtonClick}> Like </button>
</div>
</div>
</div>
);
}
});
var element = React.createElement(BoxSetup, { title : "Hello" });
ReactDOM.render(element, document.getElementById("app"));
})();
What you are wanting to do does not seem possible. Once the user clicks on the <a> enclosed content they will be redirected to the linked content, in your case: http://www.google.com
If you want to execute your function then follow the link you must remove the <a> tag and put window.location = "http://www.google.com"; at the end of your function.
One way this can be done is by setting a reference to the anchor element, then using the button elements onMouseEnter and onMouseLeave to programatically change the anchor elements href property whenever the user moves the mouse over the Like button.
class Test extends React.Component {
constructor(props){
super(props)
this.state={ likes:0 }
this.anchorElement=null;
}
enter = () => { this.anchorElement.href='javascript:;'; }
leave = () => { this.anchorElement.href='http://www.google.com'; }
handleClick = () => { this.setState({ likes: ++this.state.likes}); }
render() {
return (
<div>
<div>{'Likes:'+this.state.likes}</div>
<a href="http://www.google.com" ref={(el) => { if (el) { this.anchorElement = el; } }}>
<div>
<h2 className="title">Random Title</h2>
<button onClick={this.handleClick} onMouseEnter={this.enter} onMouseLeave={this.leave}> Like </button>
</div>
</a>
</div>
);
}
}
See it in action: Working fiddle
In the fiddle you will note the link is activating, but is not going anywhere because it is effectively "turned off" while the button is under the mouse. If you want to get rid of the appearance of activation on the link, a little more manipulation of the anchor element is needed, or simply set the a:active css property to the same color as the base/active color.
Personally, I would avoid the scenario if possible, but that's just good advice, something that more folks around here should learn is not the same thing as an answer.

How to edit an element's text with React.js?

i wanna edit my p element's text when i press edit button.
When i click edit button, i display a textarea and get keyed text with alert but can't put that text to my p element.
What is the simple way to do it with React.js ?
JSFIDDLE
When i press edit button, editing state changing and textarea shows up.The code below.
renderNormal: function() {
return (
<div>
<p>Edit me</p>
<button onClick={this.edit}>Edit</button>
</div>
)
},
renderForm: function() {
return (
<div>
<textarea ref="newText" defaultValue="Edit me"></textarea>
<button onClick={this.save}>Save</button>
</div>
)
},
render: function() {
if (this.state.editing) {
return this.renderForm()
} else {
return this.renderNormal()
}
}
You need to store and retrieve the text from a state variable. Modifying the state causes a re-render, which will then display the updated text. Copied from your JSFiddle... note where I've added a "text" property to your state
var MyCom = React.createClass({
getInitialState: function() {
return {
editing: false,
// ** Initialize "text" property with empty string here
text: ''
}
},
edit: function() {
this.setState({
editing: true
})
},
save: function() {
var val = this.refs.newText.value;
alert(val)
this.setState({
// ** Update "text" property with new value (this fires render() again)
text: val,
editing: false
})
},
renderNormal: function() {
// ** Render "state.text" inside your <p> whether its empty or not...
return (
<div>
<p>{this.state.text}</p>
<button onClick={this.edit}>Edit</button>
</div>
)
},
renderForm: function() {
return (
<div>
<textarea ref="newText" defaultValue="Edit me"></textarea>
<button onClick={this.save}>Save</button>
</div>
)
},
render: function() {
if (this.state.editing) {
return this.renderForm()
} else {
return this.renderNormal()
}
}
})
ReactDOM.render(
<div>
<MyCom/>
<MyCom/>
</div>,
document.querySelector(".box")
)
You have to set a value on the state on the button is clicked, and then read that on render.
Example:
handler : function () {
this.setState({ value : 'hey' });
},
render : function () {
return <p>{ this.state && this.state.value ? this.state.value : 'hoy' }</p>;
}
Everytime you want the render method to change according to something that can happen, the action that triggers it must trigger a state change, and change the state object, and the object will be rerendered, so the render method should check the current state.
If you want to change the value of a input (or in your case, a textarea), you can use the linkedstate pattern as a two way databinding (more here).
I particularly use this lib. There are plenty of examples there.
I actually had this same problem, here was my solution:
{editableSubTasks.filter(id => id === subTask.Id).length > 0 ? <input type="text" /> : <span>{subTask.Name}</span>}
So basically, you have an array, in my case it was editableSubTasks. Whenever I would trigger the text element to change to a textarea, I would simply add that guy to the edtiableSubTasks array. And then in my map function, if the Id of the correspnding item was in the editableSubTasks array, I would use a ternary operator to tell it to be a <input type="text">, otherwise just a span. In your case obviously you can use a textarea. This worked out wonderfully. Here was my SO with the answer that I ended up using:
How to dynamically show/hide a list of items in react
If you don't need the array, then the answer is even simpler, just have a bool and change it to true when you want it to be a text area.

react js , get siblings or parent value

I'm new to react, I'm curious how to do this properly.
suppose I have this form, by clicking button, I want to get textbox value,
var form = React.createClass({
submit : function(e){
//how to get textbox value?
},
render : function(){
return (
<form>
<input type="text" id="textbox" value="hey, get me"/>
<button onClick={this.submit}>Get it</button>
</form>
);
}
});
Any answer will be appreciated! thank you!
React enforces parent-to-child unidirectional data flow.
So, there's no simple way to access data from siblings.
But, if a child changes the state across the component, you probably want a state for keeping a track of that.
Sample code:
var FormBox = React.createClass({
getInitialState: function () {
return {
textBox: 'hey, get me!'
}
},
pressButton: function () {
alert(this.state.textBox)
},
textChange: function (e) {
this.setState({
textBox: e.target.value
})
},
render: function () {
return (
<form action='.'>
<input type='text' placeholder={this.state.textBox} onChange={this.textChange}/>
<button onClick={this.pressButton}> Get it </button>
</form>
)
}
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
JSBin demo: https://jsbin.com/koxujuwope/edit?js,output
Also, just a suggestion... You should move to ES2015
One way to accomplish this is using refs.
After building your component, you may find yourself wanting to "reach
out" and invoke methods on component instances returned from render(). link to refs docs
Refs are basically the html elements / react instances you want to access. In this case, we want to get Input html element. We get input element by this.inputValue. Then read its value by usual js rule.
var form = React.createClass({
submit : function(e){
e.preventDefault();
console.log(this.inputValue.value);
},
render : function(){
return (
<form onSubmit={this.submit}>
<input type="text" id="textbox" defaultValue="hey, get me"
ref={ function(node){ this.inputValue = node }.bind(this) }
/>
<button onClick={this.submit}>Get it</button>
</form>
);
}
});
here is a jsfiddle for your example, you can check the console for the input value.
Another way to accomplish the same thing is to make your input a controlled element. That means you assign input's value attribute to this.state.inputValue and you pass a onChange event handler as onChange={yourInputHandlerFunction}.
See the answer which explains this way of accomplishing the same thing.
The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls.
It is based on https://reactjs.org/docs/refs-and-the-dom.html
class App extends React.Component<IAppProps, IAppState> {
private _navigationPanel: NavigationPanel;
private _mapPanel: MapPanel;
constructor() {
super();
this.state = {};
}
// `componentDidMount()` is called by ReactJS after `render()`
componentDidMount() {
// Pass _mapPanel to _navigationPanel
// It will allow _navigationPanel to call _mapPanel directly
this._navigationPanel.setMapPanel(this._mapPanel);
}
render() {
return (
<div id="appDiv" style={divStyle}>
// `ref=` helps to get reference to a child during rendering
<NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
<MapPanel ref={(child) => { this._mapPanel = child; }} />
</div>
);
}
}

Kendo-Knockout: Cannot call a function within template

I want to call the onHover function but with no suceess. The only way I managed to do this is if the function is global, but this is no what I need.
What I am trying to do is onMouseOver of some element of the dropdown to take its value and do something with it in my viewmodel.
HTML:
<div>
<div data-bind="with: myInnerViewModel">
<input type="text" data-bind="kendoDropDownList: {data: myData, value: myValue,template:'<span onMouseOver = \'onHover(this)\' title=\'${data}\'>${data}</span>'}" />
<div>
</div>
JS:
var myViewModel = function () {
this.myInnerViewModel = {
myData : [1, 2 , 3],
myValue : ko.observable(1),
onHover : function(e){
alert(1);
}
};
};
ko.applyBindings(new myViewModel());
fiddler: http://jsfiddle.net/QZWPR/30/
The issue lies with location of your function. If you were to change
onMouseOver = \'onHover(this)\'
to
onMouseOver = \'myViewModel.myInnerViewModel.onHover(this)\'
then i expect you would see your alert.
OR
you need to use the event binding on your span
<span data-bind="event: { mouseover: onHover}">

Categories