Inline arrow function click listener - javascript

This is my html code:
<button id ="btn-birthdate" class = "mdc-icon-button material-icons" >
<i class="material-icons" >stop</i>
</button>
This is my javascript code
const displayExtraUserInfo = (userInfo) => {
const btn = () => {
document.querySelector('btn-birthdate').onclick = displayBirthdate(UserInfo);
}
}
But I keep getting the message
You have not created the onclick listener for the btn-birthdate as
specified
...when I run in Sapio
Question am trying to solve
Create a displayExtraUserInfo arrow function. It should take in a single parameter. It should then:
Add an inline arrow function click listener to the BUTTON with id of btn-birthdate. The listener should make a call to displayBirthdate and pass in the parameter displayExtraUserInfo received

In the onclick assignment you are currently executing displayBirthdate immediately, instead of assigning a function.
So change
.onclick = displayBirthdate(UserInfo)
to:
.onclick = () => displayBirthdate(UserInfo)
On the other hand, you never call the btn function after having defined it. Either add a call btn() or just don't define that function at all, and just execute its code inline.
There is also a problem with the selector. You are selecting an element of which the tag name is btn-birthdate, but you should select by the id. #btn-birthdate.
And there is yet another mistake: the spelling of userInfo should be consistent, otherwise you are dealing with another variable.
So the final solution would be:
const displayExtraUserInfo = (userInfo) => {
document.querySelector('#btn-birthdate').onclick = () => displayBirthdate(userInfo);
}
Finally, the question says you are looking for a button. Although an element id is supposed to be unique, you could add the button in the selector:
const displayExtraUserInfo = (userInfo) => {
document.querySelector('button#btn-birthdate').onclick = () => displayBirthdate(userInfo);
}

The querySelector method uses CSS selector formatting, so querySelector('btn-birthdate') is not going to find anything. You need querySelector('#btn-birthdate') to target the id "btn-birthdate".
You could also use document.getElementById("btn-birthdate")

This works for me
const displayExtraUserInfo = (userInfo) => {
document.getElementById('btn-birthdate').addEventListener('click',()=>{
displayBirthdate(userInfo)
} );

Related

How to get clicked button that was created dynamically?

I am trying to get a dynamically created button in order to access its parent.
I already tried to do:
var btn = document.createElement("BUTTON");
btn.innerHTML="Add";
addButton.appendChild(btn);
btn.addEventListener("click(this)", add);
sadly the button won't work if i type "click(this)". It only works if I type "click".
Changing the method to function add(element) from function add() also did not work.
How can i access the parent of my clicked button?
I cant create my buttons in HTML since i am creating a dynamic list of buttons which may differ depending on the size of the array.
Also my code should only be in Javascript
Thanks for the help!
By magic, I mean by the standard, the button reference is passed to the object.
function add() {
console.log(this);
}
var btn = document.createElement("BUTTON");
btn.innerHTML="Add";
addButton.appendChild(btn);
btn.addEventListener("click", add);
<div id="addButton"></div>
If you really wanted to pass along a variable
function add(btn, what) {
console.log(btn, what);
}
var btn = document.createElement("BUTTON");
btn.innerHTML="Add";
addButton.appendChild(btn);
btn.addEventListener("click", function(){ add(this,'foo'); });
<div id="addButton"></div>
Check this : https://www.w3schools.com/jsref/met_document_addeventlistener.asp
You should use btn.addEventListener("click", () => {}) instead of btn.addEventListener("click", () => {}).
But I think it would be better to use document.addEventListener((e) => {}) and then check the target (e.target)

Is it possible to have acces to innerHTML 'id' from otger part of the code?

I have following code, where, based on event, I add some html code. I would like to refer to 'id' from this dynamically injected html in other event (or just from other part of the code):
<div id="choice"></div>
var decisionList = document.getElementById("decisionList");
decisionList.addEventListener("change", function () {
var finalChoice = document.getElementById("choice");
finalChoice.innerHTML='<input id="finalDate" type="date">'
}
and other event referring to 'id' from innerHTML:
var payment = document.getElementById("finalDate");
payment.addEventListener("change", function () {
var textDate = payment.textContent;
alert(textDate);
})
The above is not working. Is it possible or not?
It is possible, but make that payment getter lazy. What that means is, instead of setting up that second change listener right away (in your other code), make that other code a function. Then in your first trigger, where you created the extra div or input or something, call that setup function.
decisionList.addEventListener("change", function () {
const finalChoice = document.getElementById("choice");
finalChoice.innerHTML='<input id="finalDate" type="date">'
createFinalDateListener();
}
function createFinalDateListener() {
const payment = document.getElementById("finalDate");
payment.addEventListener("change", function () {
const textDate = payment.textContent;
alert(textDate);
});
}
Here's a similar example. I do not have the input immediately. Or listener. And I only create a listener after I create the input.
// Here's the main trigger
function addExtraElements() {
// let's create a datepicker dynamically.
document.querySelector('#placeholder').innerHTML = '<input type="date" placeholder="pick date">';
listenDateChanges();
// TODO: don't forget to add cleanup code! Each time you fill that innerHTML, the old listener will remain
}
// Here's your datepicker listener
function listenDateChanges() {
const datePickerEl = document.querySelector('input[type="date"]');
if (!datePickerEl) {
console.log('no picker');
return;
}
datePickerEl.addEventListener('change', () => alert(datePickerEl.value));
}
<div id="placeholder">
Placeholder
</div>
<button onclick="addExtraElements()">Add extra elements</button>

Cleanest way for allowing HTML's onClick to access a module's function?

Say I have a class:
export default class SubmitModal {
constructor () {
this.element = document.createElement('div')
this.element.classList.add('modal')
this.element.innerHTML = this.generateContentHTML()
}
generateContentHTML () {
return `
<div class='modal-content'>
a bunch of other things
<button onClick={this.submit()}>Submit</button>
</div>
`
}
submit () {
console.log('submitted!')
}
}
What would be the cleanest way for the button element to access this.submit?
I could make the submit function a global by appending it to the window variable; however, that seems bad in the long run (if I have two submit functions, etc.).
I also realize that I could simply create a button element and add and event listener to it, but is there any way I could do the same utilizing HTML's onClick?
Thanks
Don't create it as HTML. Create the button using document.createElement(), then use addEventListener() to add the class method as the listener.
export default class SubmitModal {
constructor () {
this.element = document.createElement('div')
this.element.classList.add('modal')
this.element.appendChild(this.generateContent());
}
generateContentHTML () {
let div = document.createElement("div");
div.classList.add("modal-content");
div.innerHTML = `a bunch of other things`;
let button = document.createElement("button");
button.innerText = 'Submit';
button.addEventListener("click", () => this.submit());
div.appendChild(button);
return div;
}
submit () {
console.log('submitted!')
}
}
You have to access it with an arrow function to make it work completely correctly:
<button onClick={() => this.submit()}>Submit</button>

How to access more than one button from 1 onClick function in React?

I've made a function, which will be called when a button is clicked. I want to use it for two buttons, but after implementing it, when I click on one button, both get clicked at the same time?
This is the function, which will be called after onClick -
showMore = () => {
this.setState((prevState) => {
return { showMore: !prevState.showMore };
});
};
This is the condition I've used to call those two buttons (I know, I can do something here to make it just two if conditions rather than 4, suggestions?)
if (!this.state.showMore) {
accounts = take(accounts['demo_accounts'], DEFAULT_NO_OF_ACCOUNTS);
}
if (this.state.showMore) {
accounts = accountsData['demo_accounts'];
}
if (!this.state.showMore) {
cardNumbers =
take(cardNumbers['demo_numbers'], DEFAULT_NO_OF_ACCOUNTS);
}
if (this.state.showMore) {
cardNumbers = accountsData['demo_numbers'];
}
And I am using it for 2 buttons, however, both the buttons are getting clicked at the same time, I know I can use an ID for button, but that doesn't seen to work as well.
To sum it up, two questions basically -
How to reduce the 'if' statements?
How to stop both the buttons getting clicked?
Similar answer, but you can set it so that each button has a different ID and attaches to a different event handler, like so:
<button id="btn1">Click me!</button>
<button id="btn2">Me too!</button>
Javascript:
const button1 = document.getElementById("btn1").addEventHandler('click', function);
const button2 = document.getElementById("btn2").addEventHandler('click', function2);
How to reduce the 'if' statements?
Just combine the like conditions. Since all your conditions are basically checking the value of this.state.showMore you really only need 1 single conditional test.
if (this.state.showMore) {
accounts = accountsData['demo_accounts'];
cardNumbers = accountsData['demo_numbers'];
} else {
accounts = take(accounts['demo_accounts'], DEFAULT_NO_OF_ACCOUNTS);
cardNumbers =
take(cardNumbers['demo_numbers'], DEFAULT_NO_OF_ACCOUNTS);
}
How to stop both the buttons getting clicked?
When I want to use a single general click handler across multiple buttons I use a Higher Order Function, which is a function that returns a function. So in this case I create a clickHandler = id => () => this.setState({ [id]: <value> });
This callback takes an id parameter that is used when attaching the callback to the onClick handler of an element, and it is invoked right away and returns a new function that is actually used as the callback with the id saved in the enclosure.
<button onClick={this.clickHandler('a')>Button A</button>
<button onClick={this.clickHandler('b')>Button B</button>
Here is a codesandbox example of a HOF handler

How to focus cursor on a stripe input element

I am trying to add in a credit card form with Stripe Elements (https://stripe.com/docs/stripe-js/reference#other-methods).
Normally I would focus on an element by doing:
$('input[type="tel"]').focus()
However, this doesn't work with the Stripe credit card input. However, the following does work:
$('input[type="tel"]').value='asdf'
So it is grabbing the correct item. How would I focus the cursor on the input item? It seems like it may be inside an iframe, even though I can write a value to it in jquery/javascript.
The element needs to be fully initialized before you can call focus(). Ensure the element is ready with a simple event handler:
element.on('ready', () => {
element.focus()
})
You should use the focus() method on the element that you created and not the div itself.
For example you can have a button that gives focus to the CVC element (assuming split fields) by doing
document.getElementById('give-focus').addEventListener('click', function () {
cardCvcElement.focus();
});
You can see this in action here: https://jsfiddle.net/4c72oyap/
let elements = stripe.elements();
let cardCvcElement = elements.create("cardCvc");
cardCvcElement.mount("#card-cvc-element");
let cvc = document.querySelector("#card-cvc-element");
cardCvcElement.addEventListener("blur", () => {
cvc.style.removeProperty("border");
});
cardCvcElement.addEventListener("focus", () => {
cvc.style.setProperty("border-color","red");
}
});
You can trigger the focus method after your element created when it's ready
Example:
var cardElement = elements.create('cardNumber', { showIcon: true, style: style, classes: elementClasses });
cardElement.mount('#card-element');
cardElement.on('ready', (e) => cardElement.focus());
If you are using Stripe-react-js SDK, here is how to focus:
<CardElement
options={CARD_ELEMENT_OPTIONS}
onReady={(e) => e.focus()}
/>
Link to official docs https://stripe.com/docs/stripe-js/react#element-components

Categories

Resources