svelte: click event triggered on wrong button - javascript

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

Related

How do I console.log the result of a foreach loop with a 'click' function?

Apologies if this is really simple but I have been researching this for a week now but can't find the right thing to type into google.
I have 3 buttons as shown below:
const playerSelection = document.querySelectorAll(".buttons").forEach(e => {
e.addEventListener('click', function() {
return e.innerHTML;
})
});
console.log(playerSelection);
<div>
<button class="buttons">Rock</button>
<button class="buttons">Paper</button>
<button class="buttons">Scissors</button>
</div>
When I console.log playerSelection it only returns undefined. I want the playerSelection variable to equal the innerHTML content of whichever button I click.
Help is appreciated.
You log the value of the button inside the click event.
Also you should set the type of your buttons to button, otherwise they are of type submit, which I guess you don't want here.
document.querySelectorAll(".buttons").forEach(e => {
e.addEventListener('click', function() {
console.log(e.innerHTML);
})
});
<div>
<button type="button" class="buttons">Rock</button>
<button type="button" class="buttons">Paper</button>
<button type="button" class="buttons">Scissors</button>
</div>
You're probably thinking of Array.prototype.map, which combines the returned results into an array.
This won't work in your case, though, as you are simply adding an event listener inside your loop. The event callback will only be triggered when the button is clicked. You'll need to write asynchronous code. For example, when a button is pressed, call a function pickedValue() with the result, which will then continue your program.

onClick attribute for JSX react element not working as expected

The onClick attribute for a button element created within a variable is not firing.
I tried directly defining the function in the onClick attribute, and simply out-putting to the console, but there is still nothing output to the console, and the button is not working as expected.
I also added a 'disabled={false}' attribute to the button to make sure that was not an issue, but the onClick attribute is still not working as expected.
let display = (<div className ='dtaskhome'>
<h1>Tasks</h1>
<button disabled={false} onClick={newTask} className='btask'>New Task +</button>
<ul className ='ultasks'>{taskItems}</ul>
</div>);
function newTask() {
console.log('point reached');
Tasks.props.state.newTask = true;
}
No error messages related to the onClick attribute are being displayed, and the current code correctly renders the component.
I also added a 'disabled={false}' attribute to the button to make sure
that was not an issue, but the onClick attribute is still not
responsive.
Try implementing the function as a method.
newTaskHandler = (props) => {
console.log('point reached');
props.state.newTask = true;
}
Then try
onClick={this.newTask(this.props)}
Hope this helps you.
try to call the function:
onClick={newTask()}
And if not try to call it with this.
onClick={this.newTask()}

Is there a way to add a function on close of ng-multiselect-dropdown?

I am using the ng-multiselect-dropdown package in angular 5 for creating a multi-select dropdown.
I want to do call a function on close or hide of the drop-down component.
like this
closeDropdown : function(){
console.log("dropdown close triggered");
}
According to the documentation you can pass closeDropDownOnSelection value true to close the dropdown whenever the selection is done
ng-multiselect dropdown
Incase of multiple selection you can call (onSelect)="onItemSelect($event)"
for more information check this Demo documentation
You can call the function within (change) event.
ex :
<ng-multiselect-dropdown
(blur)="closeDropdown($event)"
>
</ng-multiselect-dropdown>
To solve the bug identified by satira ( I couldn't comment due to low reputation), ie.
"When the component which has this multi-dropdown opens for the first time or you reload the page and click anywhere outside the dropdown, onDropDownClose() gets called." For me, it didn't happen after the first time. Anyway, i solved it by getting the id of any element on the screen(header, footer or any div) and used docuement.getElementById('element_id').click() on ngAfterViewInit.
ngAfterViewInit() { document.getElementById('header').click(); }
This made sure that no sideeffects take place on my app. I know this is a messy solution but since closeDropdown() of ng-multidropdown doesn't work, this was my only way out.
I had this issue recently and found a solution that works for me using a combination of (ngModelChange) and (click). When using ng-multiselect-dropdown the other normal HTML Element triggers like (blur) and (change) don't work, but the (ngModelChange) does work. Only problem with that is it triggers when being initialized. But I added a boolean variable to the (click) trigger that does seem to work.
Note that this also works to cover the onSelect, onDeSelect, etc
component.ts:
...
dropDownSelect: boolean = false;
dropDownSelection: number;
...
saveFunction(event) {
if(!this.dropDownSelect) return;
...
this.dropDownSelect = false;
}
component.html:
...
<ng-multiselect-dropdown [data]="dataSource" [(ngModel)]="dropDownSelection" [settings]="dropDownSettings" (click)="dropDownSelect = true" (ngModelChange)="saveFunction($event)"></ng-multiselect-dropdown>
...
I tried #misterz's solution but it didn't work. However I modified it and it works perfectly.
The trick:
In addition to (onDropDownClose), listen to a click event;
// this act as a differentiator between other calls(bug) and an intended call
(click)="dropDownSelect = true".
In your component, declare your variable and use it like this:
dropDownSelect = false;
saveFunction($event) {
if (this.dropDownSelect) {
// close the opening to subsequent actions
this.dropDownSelect = false;
// Perform action;
};
}

Javascript And Query

I am new to Javascript and trying to add a and Query to a js file.
I have added a checkbox this is required to be checked for the submit button to show.
In the original there was already one checkbox with the js query but I have added a second. How do I make the js only allow the button to be clicked when both are checked?
The current code for the js is
jQuery('.check_policy').on('click', function(){
if(jQuery('#policycheck') .is(':checked')){
jQuery("#listingsubmitBTN").prop('disabled',false);
jQuery("#listingsubmitBTN").removeClass('dissablebutton');
}
else{
jQuery("#listingsubmitBTN").prop('disabled',true);
jQuery("#listingsubmitBTN").addClass('dissablebutton');
}
});
The second check box I have added is called policycheck_2
Thanks in advance for any help. I think this could be one of many js questions
Mark
jQuery('.check_policy').on('click', function(){
if(jQuery('#policycheck').is(':checked') && jQuery('#policycheck_2').is(':checked')){
jQuery("#listingsubmitBTN").prop('disabled',false).removeClass('dissablebutton');
}
else{
jQuery("#listingsubmitBTN").prop('disabled',true).addClass('dissablebutton');
}
});
Edit: Just add an AND (&&) operator with the same syntax with the new ID as the first one in the if statement.
I'll also shortened the rest a little bit, looks nicer. :-)
Separate the responsibilities.
Bind the click event to the checkboxes. The handler only has to trigger the event on the specific button.
Bind a custom event to your button which validates the checked boxes.
Use this condition to disable or enable:
$('.check_policy').length !== $('.check_policy:checked').length
$('.check_policy').on('click', function() {
// Here we trigger the custom event.
$('#listingsubmitBTN').trigger('validatechecked');
// Now this handler only trigger events to specific elements and not
// everything mixed here.
});
$('#listingsubmitBTN').on('validatechecked', function() {
$(this).prop('disabled', $('.check_policy').length !== $('.check_policy:checked').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class='check_policy' type='checkbox'>Check policy#1
<p>
<input class='check_policy' type='checkbox'>Check policy#2
<p>
<input type='button' id='listingsubmitBTN' value="Click me!" disabled>
Your main issue is that your if statement is not checking if both checkboxes are checked - it still only checks to see if #policycheck is checked to determine the disabled status of the button. A simple fix would be to add the jQuery("#policycheck_2").is(":checked") to your if statement, and your code will work - however, you can leverage using an expression in the prop setter function, as well as the toggleClass function to simplify/shorten/clean-up your code a bit.
Here's an example of what that would look like:
jQuery('.check_policy').on('click', function() {
var bothChecked = jQuery("#policycheck").is(":checked") && jQuery("#policycheck_2").is(":checked");
jQuery("#listingsubmitBTN").prop("disabled", !bothChecked).toggleClass("dissablebutton", !bothChecked);
console.log("button", bothChecked ? "enabled" : "disabled");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="policycheck" />
<input type="checkbox" id="policycheck_2" />
<button class="check_policy">Check Policy</button>

Why doesn't react disable the onClick handler when disabled is true?

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

Categories