onClick function for the specific item in a map function - javascript

I have objects stored in my state (workitems) with different attributes such as id, title, description etc. I map them out in my render in a table to make them visible. So far so good. But when I try to ad a "onClick" inside of the map function, it will not only trigger for the specific element that was clicked on, but all workitems object in the map will trigger as well.
In my render;
{workitem.company ? workitem.company + " - " : ""}
{workitem.title}
<div className="description pt-2" onClick= {this.descriptionPopOut(workitem.description)> // My onclick function
<strong>Description: </strong>
{workitem.description ? this.trimWord(workitem.description.replace("...", ""), 850, "...")
: ""}{" "}
...
</div>
The onClick will lead to a very simple function that has an alert, and take the object description as input.
descriptionPopOut = (description) => {
alert(description);
}
Above will make the alert pop out with all the object description property, and not for the specific element that has been clicked. Is there any way to solve this?

Its because on each render your function is calling i.e
this.descriptionPopOut(workitem.description)
. While you want to call on when you click. You can either bind the function so that you can use it later when you click :
this.descriptionPopOut.bind(this, workitem.description)
or you can use fat arrow function to return function i.e
onClick = {() => this.descriptionPopOut(workitem.description)>
(It ensure it creates function reference and when you click it, it invokes your function with specific param)

You are calling function in each iteration.
Try doing like this:
this.descriptionPopOut.bind(this, workitem.description)

The problem is you are calling your function incorrectly.
Don't do this onClick = {this.descriptionPopOut(workitem.description)>
Since you want to pass a parameter do this
onClick = {() => this.descriptionPopOut(workitem.description)>

Related

How to pass a parameter and get the event caller JS

I need to pass parameter from HTML to the JS function. I can't set unique id, because elements are in loop. So it looks like this:
#foreach ($meals as $meal)
<button class="btn btn-primary" onclick="addToCart('{{ $meal->id }}')">
#endforeach
But in calling function, I need access both to input parameter and event caller:
let addToCart = (id, caller) => {
console.log(id);
console.log(caller);
}
I tried to put this as second parameter, when calling function:
<button class="btn btn-primary" onclick="addToCart('{{ $meal->id }}', this)">
Well, it works, but my next task is to replace event caller with some other DOM element, using JQuery.
let addToCart = (id, caller) => {
caller.replaceWith("<h1>helloworld</h1>");
}
Unfortunately that replaces event caller with that, only as innerHTML of parent element, without interacting with tags. So, I'm getting smthing like this:
What can I do in that case?
UPD:
I'm getting this:
But I need THIS:
In case you meant to replace the button that fired the click event with a different html object instead of just replacing its text content like you did in your example, the key was using replaceWith on a jQuery object instead of calling it from an HTMLDocument.
The difference between https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceWith and https://api.jquery.com/replacewith/
So to force the invocation from the jQuery object, just use $(caller)
let addToCart = (id, caller) => {
$(caller).replaceWith( "<h1>helloworld</h1>" );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btn btn-primary" onclick="addToCart('id', this)">click to replace</button>

Automatically fill function arguments

in java and in android studio when we write a function like this:
function test (View v) { ... }
and put it in xml layout
<TextView
android:onclick="test" />
v as an argument filled automatically by java and when we click at that TextView v filled with property of that TextView clicked on
how can I define this in javascript and html tags ?
Thanks.
You can do something like this
function myFunction(element) {
element.innerHTML = "hello";
}
<button onclick="myFunction(this)">Click me</button>
Pass the clicked element that is stored in this as a parameter to the click function.
All you need to do is to add the "this" keyword, "this" keyword automatically gets the action of the current element if it clicked, checked, etc in cases of buttons, check-boxes, respectively...
I totally agree with Costin here.
HTML :
<button id="btn" onclick="someFunction(this)">Tap It</button>
JS:
function someFunction(element) {
element.innerHTML = "hello";
}
which means the someFunction will automatically get that the element is "button" here and on its click, the action needs to be performed is to change its HTML and display "hello".

How do I create a button component that takes parameters on its onClick method in React?

Okay, I've been working at this for 2 days now and I need some help. I previously made a loot logging program for a game I play, and now I want to make it into a Webapp. I'm using React JS to build the app.
I need to make a button component that includes an onClick function and can take parameters. My app renders buttons equal to the length of the loot table for the selected monster (so only the number of buttons needed are made) using a for loop. These buttons need to have an onClick method that takes a value parameter (the value is the index of an array if it matters. The array stores the loot table).
I thought I could just generate the button name by referencing {this.props.name} and the value it needs to pass by using {this.props.value}.
var Button = React.createClass({
render: function() {
return <button type="button" onClick={this.onClick.bind(this,
{this.props.id})}>{this.props.name}</button>
},
onClick: function(value) {
alert(value);
}
});
React.render((<Button name="test" id={1} />),
document.getElementById('example'));
For testing purposes, the button is just drawn in a div with class 'example'.
I've tried to find the examples of something like this working, but I can't find anyone who wants to dynamically create buttons that also pass parameters like I need to do for my webapp. Thank you for any assistance!
Look at the following code you wrote:
return <button type="button" onClick={this.onClick.bind(this,
{this.props.id})}>{this.props.name}</button>
There is an error in the onClick binding. it should look like this:
return <button type="button" onClick={this.onClick.bind(this,
this.props.id)}>{this.props.name}</button>
There are redundant brackets around this.props.id
You could just create a closure for each button's onClick while generating them:
const Button = ({ name, onClick }) => {
return (
<button onClick={onClick}>{ name }</button>
)
}
const List = () => {
return (
<div>
{ [0,1,2,3,4,5,6,7,8,9].map((value, index) => {
const onClick = () => { /* use index here */ }
return <Button onClick={onClick} name={value}/>
}) }
</div>
)
}
as an example. keep in mind I'm using ES6/JSX instead of React.createClass (for my sanity and because it's what I'm familiar with).
Besides, it doesn't make sense for the button to be responsible for handling the onClick logic - it should only be responsible for passing the event back to the relevant "subscribers"

Stop click event firing last thing that got appended

I have this fiddle : https://jsfiddle.net/cs3xt67j/3/
It creates new divs with tabs on the click of the button. I have added an eventListener on each tab which is suppose to hide every div inside a container except the one that relates to that tab :
function showThisDiv(selection){
console.log(selection)
var children = document.getElementById('mainContainerDiv').childNodes;
for(i=0;i<children.length;i++){
if(selection!=children[i].id){
document.getElementById(selection).classList.add('hidden');
}
document.getElementById(selection).classList.remove('hidden');
}
console.log(children)
//document.getElementById(selection).classList.remove('hidden');
}
I added this event when i first create the divs (in the function that gets called from button click ) like so :
newDivTab.addEventListener("click",function(){ return showThisDiv('containerDiv'+divCount)});
But every time the event fires, it calls the last selection that got added to event rather than the thing that got added when i created the divs. Probably easier if you see the console log from the fiddle. Just create a few tabs by clicking the button and click the tabs created then see console logs
Working demo.
Basically you need to duplicate value of divCount and store it into other context to preserve it's value.
So, instead of:
newDivTab.addEventListener("click",function(){ return showThisDiv('containerDiv'+divCount)});
Use:
var localCount = divCount;
newDivTab.addEventListener("click",function(){ return showThisDiv('containerDiv'+localCount)});
Every time a div is clicked it calls the function
function(){ return showThisDiv('containerDiv'+divCount)}
so the concatenation of the string 'containerDiv'+divCount doesn't get evaluated until the click, so it is using whatever the current value of divCount is, so the possible div.
These are called closures and a lot smart people have written about them: http://www.mennovanslooten.nl/blog/post/62
To fix wat you're doing i would suggest wrapping the onclick function in another function and pass it the wanted id
newDivTab.addEventListener("click",(function(divID){
return function(){
showThisDiv('containerDiv'+divID)
}
})(divCount))
To quote the link above (with i being equivalent to your divCount):
Calling this function creates a new variable scope for each iteration because variable scope is created at execution time. This allows me to pass on the value of i to this new scope.

Why are only some attributes updated from my javascript function?

I have a button script to change the buttons in a frame based on the page loaded in the main frame. The problem I'm experiencing is that while the background images, tabindex and text on the button (innerHTML) all change as expected, the onclick doesn't. It appears to completely ignore it. Here's the script I'm using:
function createbutton(btn_N, btn_I, btn_L, btn_D) // (Div Name, Tab Index, Button Text, Page To Load){
var btnN = top.frames['buttonbar'].document.getElementById(btn_N);
btnN.style.cssText = "display:block; cursor:pointer; padding-left:16px; padding-top:5px;";
btnN.onmouseover = function() {this.style.backgroundImage = "url('./osdimages/navBG_roll.png')";};
btnN.onmouseout = function() {this.style.backgroundImage = '';};
btnN.tabindex = btn_I;
btnN.innerHTML = btn_L;
btnN.onclick = btn_D;
}
The button call looks like this:
createbutton("button01", 1, "New Order/Browse", "parent.frames['content'].location.href='createorder/createorder.asp';");
There is a difference between attributes and properties.
The best example of this is as follows:
HTML: <input type="text" value="hello" id="test" />
Type something in the text box
document.getElementById('test').value is whatever you typed
document.getElementById('test').getAttribute("value") is whatever was in the HTML
Some attributes are directly mapped to properties and vice versa, but this is not always the case.
For instance, the onClick attribute takes a string that is then eval'd, but the onclick property takes a function. This is why your code isn't working.
Either pass a valid function, or use setAttribute.
You are setting onclick with a string, it needs a function to execute.
createbutton("button01", 1, "New Order/Browse", function(){ parent.frames['content'].location.href='createorder/createorder.asp'; });

Categories