I'm trying use React events to access a custom 'value' assigned to a button, but I get different results depending on where I click on the button. I can probably use getDOMNode() or this.state to get the desired result but I'm little confused on how to use 'React Events' and it's behavior.
Is it best to use synthetic events on a single element like <input>? Is there a way to get the value of a button using react events?
Note: I'm using bootstrap glyphicon inside the <button> element.
var Content = React.createClass({
handleClick: function(e) {
console.log( e.target );
},
render: function() {
return (
<div>
<button type="button" value="button1" className="btn btn-default" onClick={this.handleClick}><span className="glyphicon glyphicon-ok"></span> Submit</button>
</div>
)
}
});
Jsfiddle
console.log( e.target ) results:
Move the mouse over the glyphicon 'check mark', and click.
<span class="glyphicon glyphicon-ok" data-reactid=".0.0.0"></span>
Move the mouse over the word 'Submit' and click
<span data-reactid=".0.0.1"> Submit</span>
Move the mouse anywhere else inside the button, and click
<button type="button" value="button1" class="btn btn-default" data-reactid=".0.0"><span class="glyphicon glyphicon-ok" data-reactid=".0.0.0"></span><span data-reactid=".0.0.1"> Submit</span></button>
I'm new to synthetic events and DOM behaviors as you guys can tell. Any guidance would be greatly appreciated! Thanks.
I think you want e.currentTarget.getAttribute('value')
Using currentTarget will get the button since the event will bubble up to the button. You are getting the span element since you're likely clicking the span. That's what the value of target is.
Also here is the updated fiddle: http://jsfiddle.net/v27bqL5y/1/
Another way to do this is to use refs. If you want to stay away from using stuff like e.currentTarget, this can be a simpler way to go.
See the fiddle: http://jsfiddle.net/v27bqL5y/2/
Related
I have a svelte app where
licking a button "Show" sets a show variable to true which shows a input text box and a save button.
Clicking the "Save" button calls a function which sets the show variable to false
Testing shows that clicking Show also triggers the on:click of Save.
Google tells me to add stopPropagation to fix this issue, but it does not fix this issue.
Any hints on what is my mistake?
A repl with my code is available at
https://svelte.dev/repl/592a544ac59a45b385ab153dec7a42f1?version=3.55.1
I forked the repl and made some changes to it
https://svelte.dev/repl/b897aa42e87d4adc8c04b381b5a66692?version=3.55.1
Here is the new code:
<script>
var name = ''
let names=[];
let show=false;
function addName(){
console.log("Clicked");
show=false;
if (name.length > 0){
names.push(name);
console.log(names)
}
}
</script>
<button on:click={()=>(show=true)} > Show
</button>
{#if show}
<input bind:value={name} type="text">
<button on:click={()=> {addName()}}>Save</button>
{/if}
<h1>Hello {name}!</h1>
You shouldn't have a propogation issue because the event listeners are not nested elements https://www.tutorialrepublic.com/javascript-tutorial/javascript-event-propagation.php
Your Save button on:click was setup like
<button on:click={addName()}>Save</button>
This definition is not correct because on:click={addName()} calls the addName function immediately. If you use this syntax you likely need to write it like this
on:click={addName}
Otherwise you can write it like your other on:click with an anonymous function (which is what I did).
on:click={()=> {addName()}}
I would expect that setting the disabled attribute on a react component would block the onClick handler for that element.
<a role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
href={this.state.selectedObjectLink}
onClick={this.handleLink}
>View</a>
but although the element shows a "disabled" attribute it still registers a click event.
Edit: I should clarify - I handle the click event in handleLink, I want to know why the disabled attribute doesn't remove the handler? Sorry for any confusion.
The problem isn't with disabled; it's with the HTML element a. Anchor <a> cannot have a disabled property (what does that even mean?). Just because you've passed CSS to make the element look like a button, doesn't make it a button. It is still an anchor.
The solution would be either to use something else (like button):
<button
role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
onClick={this.handleLink}
>
View
</button>
You can use this.state.selectedObjectLink inside handleLink if you want to redirect to a page
Or use one of the many other suggestions on this page.
Why not just handle this in handleLink?
handleLink () {
if (!this.state.readyToView) return
// ...
}
If you really want to bind/remove the handler dynamically, you can do something like this:
const clickHandler = this.state.readyToView ? this.handleLink : null
...
<a role="button"
...
...
onClick={clickHandler}
>View</a>
You can add a condition in your click handler, something like this
<a role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
onClick={this.state.readyToView && this.handleLink}
>
View
</a>
jsfiddle
If you are using react version 16 and up
on onClick don't call the method directly use () => method instead like this
const handleRemoveBtnClick = () => {
...
}
<button ...onClick={() => handleRemoveBtnClick} />
Another trick to disable the click to any components is to use useState with boolean value either true to disable or false to resume the click functionality
example
export default const ElementComponent() =>{
//set the initial value of disable click to false
const [disableClick,setDisableClick] = useState(false)
const anotherFunction =() =>{
console.log("I've been run")
}
const handleClick()=>{
//if disableClick is false then run this if block, else don't do anything
if(!disableClick){
anotherFunction()
}
}
return(
<img src="..." onClick={handleClick}/>
)
}
the good thing about this is that we can pass the function as a props to another components and we can run it there, we can even let's say disable a click for let's say 1 second using setTimeout function, there are tons of way you can use this method, hope it helps anyone if you want to use onClick not only on the button element itself
Used solutions from other answers to hide Bootstrap popover on outside click.
However it then requires two clicks to open the popover again (if I closed it by clicking outside).
It works alright and opens on first click when I use the button to close it.
Here is problem recreated: http://codepen.io/olegovk/pen/BjQmQe
The html used:
<!-- Popup button -->
<a id="menu-button" class="menu-button" data-html="true" role="button" data-container="body" data-toggle="popover" data-placement="bottom">Menu</a>
<!-- Popup content -->
<div id="menu-content">
<h1>Hello</h1>
<p>Good bye</p>
Link
</div>
And the jQuery:
$('#menu-button').popover({
content: $('#menu-content').html(),
html: true
});
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined' &&
!$(e.target).parents().is('.popover.in')) {
$('[data-original-title]').popover('hide');
}
});
Any ideas why it happens and how to make popup always open on first click?
One note: I find it impossible to use this "official" solution because it makes it impossible to click on links inside popup: http://getbootstrap.com/javascript/#dismiss-on-next-click
You don't need extra Js to close the popover, as the documentation says docs
Dismiss on next click
Use the focus trigger to dismiss popovers on the next click that the user makes.
<a tabindex="0"
class="btn btn-lg btn-danger"
role="button" data-toggle="popover"
data-trigger="focus" title="Dismissible popover"
data-content="And here's some amazing content. It's very engaging. Right?">Dismissible popover
</a>
data-trigger="focus" close the popover on the next click of the users.
In many cases (mostly the rest of the code in your document) once you leave the popover, you have to regain focus on it. This event is not easily binding the click event to the html or body. Buttons tend to regain the focus much better than hyperlinks. (This is my theory, I'd question it, but it's what I've read here and there) The point is, this code works lol that's the important thing, isn't it?
I suggest you change the hyperlink to a button and style it to make it look as a hyperlink if you need to and use the code in the jFiddle provided here
$('[data-toggle="popover"]').popover();
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 &&
$('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
Here is working jfiddle
It seems disabled button "onclick" function is still fired when triggering it programmaticaly, eg:
<div>
<input type="button" onclick="save()" id="saveButton" value="save" disabled="disabled" />
<input type="button" onclick="byPassDisabled()" value="bypass disabled button"/>
<div id="counter">0</div>
function save(){
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
function byPassDisabled(){
$('#saveButton').click();
}
see http://jsfiddle.net/WzEvs/363/
In my situation, keyboards shortcuts are bound to functions triggering the ".click()" on buttons. I'll find it very annoying to have to disable the shorcuts or check if the button is disabled myself. I'd prefer a general solution fixing this problem.
But why? This behavior doesn't seem fair to me.
Any workaround?
The attribute only disables user interaction, the button is still usable programmatically.
So yeah, you gotta check
function byPassDisabled(){
$('#saveButton:enabled').click();
}
Alternatively don't use inline handlers.
$(document).on('click', '#saveButton:enabled', function(){
// ...
});
For future use...the OP code works because jQuery will still call it's own handlers even if the DOM element is disabled. If one were to use vanilla javascript, the disabled attribute would be honored.
const element = document.getElementById('saveButton');
element.click() //this would not work
You can programmatically trigger click on a disabled button.
There are ways to find if the event is a click on button by user or it has been trigger programmatically. http://jsfiddle.net/WzEvs/373/
$(function () {
$("#saveButton").on('click', function (e) {
if (!e.isTrigger) {
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
});
$("#bypassButton").on('click', function (e) {
$("#saveButton").click();
});
});
e.isTrigger is true if you call the click() programmatically. Basically you are triggering the click event manually in code.
You can trigger click still although made it disable .As Spokey said it just shows the user-interaction(the usability still persists that can be turned on programmatically) .
off or unbind the click will solve this issue.
Thanks
i have modal with button (Save)
<button type="button" class="btn btn-success btn-sm" data-dismiss="modal" onclick="do_save()">Save
</button>
how to prevent closing when do_save() function failed? (for example when some data fails to validate)
Don't use the data-dismiss="modal" and let your function close (hide) your modal:
<button type="button" class="btn btn-success btn-sm" onclick="do_save()">Save</button>
"
function do_save()
{
if(Math.floor(Math.random() * 2)==1)
{
console.log('success');
$('#myModal').modal('hide');
return;
}
console.log('failure');
return false;
}
If you catch the click-event from the button like this:
$('#buttonId').off('click').click(function(clickEvent){
//enter code here
});
you actually can prevent the closing of your modal. For this, depending on your situation, you will find these two functions useful:
clickEvent.preventDefault();
clickEvent.stopPropagation();
If I understood this site (which is in German)
http://www.mediaevent.de/javascript/event-handler-default-verhindern.html
correctly, preventDefault() stops the immediate default action (such as following a link). However, the event itself will still travel through the DOM and can be "heard" by various event listeners, one of these is the event listener that hides the modal. For this the second function is needed, which stops the event's travel through the DOM. Thus, it can't be heard by the hiding listener and the window won't be closed (hidden). Therefore, I suggest to implement the functions like so:
$('#buttonId').off('click').click(function(clickEvent){
//enter code here
var myDataIsValid = true;
// check if Data is valid => myDataIsValid = true or false
if(myDataIsValid){
//do Stuff
}else{
clickEvent.preventDefault();
clickEvent.stopPropagation();
//do other Stuff
}
});
In my code, I only need to use stopPropagation(), as my default action is wanted, so you can use the two functions independently.
note: This solution only was tested with a Firefox browser
Since you are using jQuery anyway, try not to have JavaScript/jQuery embedded in your code.
$('#buttonId').on( 'click', function () {
// either call do_save or embed the contents of do_save in here
var myDataIsValid = true; // change to call validator function
if (myDataIsValid) {
$('#myModal').modal('hide');
}
return true; // value depends on whether you want stopPropagation or not.
});
HTML:
<button id="buttonId" type="button" class="btn btn-success btn-sm">Save</button>
As an alternative, you can probably prevent closing by intercepting the 'hide' event and returning false from that.
If you are using bootstrap 4 this is called a "static backdrop" and can be achieved by adding the data-backdrop="static" attribute
<div class="modal fade" id="modalExample" data-backdrop="static">
src: Bootstrap 4 Modal - Static backdrop