const continueButton = $("<button>Doesn't work.</button>").click(() => {alert("hello")});
$(".content").append(continueButton.prop('outerHTML'));
$(".content").append ($("<button>Works.</button>").click(() => {alert("hello")}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
</div>
The reason I'm asking this question is because I need to pass the string version of some HTML to a function. For that reason, I can't use .append. but when i use the code above, it seems that the click event no longer works.
How can I get the HTML as a string, but have the click event still work?
More context: I am using a library that expects me to add HTML to it as a string. But I want to add HTML with a button on it that functions when it's clicked. I'm using jQuery to create the HTML, but when I try to pass the HTML string to the library, the buttons don't function.
You can delegate the event to the content element and use button as target selector
// add delegated event listener before inserting buttons
$('.content').on('click', 'button', (e) => console.log($(e.target).text()))
const continueButton = $("<button>Doesn't work.</button>");
$(".content").append(continueButton.prop('outerHTML'))
.append ("<button>Works.</button>");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
</div>
In line 1 the object has an event attached to it but this isn't reflected in HTML. Therefore when you add the outerHTML to an element, the browser creates a new element but events are not defined in the HTML so they don't exist.
If you embed the script inside the button HTML then it will work when you apply this HTML in different places: $('<button onclick="alert(\'hello\');">Test</button>').
Related
I use jquery and es6 template strings to create a checkbox with a label:
function createCheckBx(id, text) {
return $(`<div>
<input id ="${id}" type="checkbox"/>
<label for="${id}">${text}</label>
</div>`);
}
Now I would like to attach an eventlistener to the checkbox
checkBox = createCheckBx("42", "Answer");
cb.???.addEventListener("change", (evt) => {
// do smth. when toggled
})
but the div is not attached to the dom yet so I can't use document.getElementById (or jquery's $("#...") and I don't want to access it by any kind of index like cb.childNodes[0], since the caller can't know the index and the html structure may change. Any help?
kindly regards, AJ
Just because the element doesn't yet exist in the DOM doesn't mean you can't attach an event handler to it. The only issue in your example is the syntax you're using as you're mixing jQuery and plain JS methods. You should stick to one or the other.
As you're including jQuery in the page, here's how to make your example work:
let createCheckBox = text => $(`<div><label><input type="checkbox" />${text}</label></div>`);
let $checkBox = createCheckBox("Answer");
$checkBox.on('change', e => {
console.log(`Checkbox checked? ${e.target.checked}`);
});
// add the checkbox to the DOM at some point:
$('body').append($checkBox);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
Note that I removed the id attribute from the function which creates the element and also the HTML it generates. This is because creating id at runtime is an anti-pattern and should be avoided. Use common classes instead.
Also note that you may be better served by creating a single delegated event handler to handle all your dynamically appended content, instead of attaching an event as you create the new elements. Here's an example of how to do this:
let createCheckBox = text => $(`<div><label><input type="checkbox" />${text}</label></div>`);
let $container = $('.checkbox-container');
$('button').on('click', e => $container.append(createCheckBox("Answer")));
$container.on('change', ':checkbox', e => {
console.log(`Checkbox checked? ${e.target.checked}`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<button type="button">Add</button>
<div class="checkbox-container"></div>
help me out with this code, I am trying to assign a class to the clicked button's child element but when I fire a click event on any one of the button that class is assigned to all buttons child elements.I have written the jquery code for it mentioned below which works, but it works when i double click on one of the buttons and also the javascript code works in console but not in my js, html files i have the js block of code in $(document).ready(function(){}); function. I need help!
Html Code:
<div class="interact-Box">
<button class="p-emote"><i class="fas fa-thumb"></i></button>
<button class="p-emote"><i class="fas fa-thumb"></i></button>
<button class="p-emote"><i class="fas fa-thumb"></i></button>
<button class="p-emote"><i class="fas fa-thumb"></i></button>
</div>
Javascript Code:
$(.p-emote).on('click', ()=>{
var c = $(this).children('i');
$(c).toggleClass('interacted');
});
Use the event target (the event being the click, the target being the specific element that was clicked) by passing the event object into the callback.
$('.p-emote').on('click', (event)=>{
var c = $(event.target).children('i');
$(c).toggleClass('interacted');
});
EDIT: other answer rightly points out that you need quotes around the selector name ('.p-remote')
https://api.jquery.com/event.target/
You are missing single quotes around your selector and also don't use arrow function as it changes the way you are referencing $(this) into the window object. If you switch it back to something like the code below, you will see your children. Cheers.
$('.p-emote').on('click', function () {
var c = $(this).children('i');
console.log($(this).children('i'));
$(c).toggleClass('interacted');
});
In my application I have a help section that is only visible when this.car.helpOpen property is true, and initially the property is false:
<ion-item *ngIf="car.helpOpen">
<div class="car-help-content" item-content>
<img src="{{testURL}}" />
<p class="explanations" [innerHTML]="car.helpText"> </p>
</div>
</ion-item>
I have a method that changes the value of this.car.helpOpen to true and after that adds an event handler to all of the <a> elements(car.helpText contains <a> elements) inside the <p> element:
toggleHelp(input){
input.helpOpen=!input.helpOpen;
$("p.explanations").find("a").click(function(e){
alert(e.target.innerHTML);
});
}
But I think that the attachment of event handlers is happening before the *ngIf actually shows the help section, and that's why the event handlers don't get attached. If I remove *ngIf completely and execute the function toggleHelp(), the handlers get attached.
Is there a way I can work around this?
Maybe there is a way to add the event handlers without using jQuery? (without changing the actual innerHTML of the element)
ngIf is a structural directive, it creates/destroys content inside the DOM. you can hide the elemnt by css like add class will make the display:none
What is the difference between *ngIf and [hidden]
You can add a click event to p elemnt and check the target element if it 's a this will look like add event listener to a element with pure javascript without jquery
template
<p [innerHTML]="html" (click)="toggleHelp({},$event)"></p>
toggleHelp function
toggleHelp(input , e:MouseEvent) : void{
input.helpOpen=!input.helpOpen;
console.log('event element',e);
if ((e.target as HTMLElement).tagName === 'A') {
let target = e.target as HTMLElement;
// everything here will run if you click on a element
alert(target.innerHTML)
}
}
stackblitz example
How do I bind an html event such as onclick to a function myFunc(e){}?
I do not want to use document.getElementByClass or Id.
I do not want use jQuery.
Try this:
document.getElementsByTagName('body')[0].addEventListener('click', function(){alert("you clicked on the page")})
This adds an event listener to the body tag. Once you click on the page, it will fire the alert function.
You can get the elements by either class name, id and/or tag name:
document.getElementById('someId')
document.getElementsByClassName('someClassName')
document.getElementsByTagName('body')
Keep in mind, the "getElementsByClassName" and "getElementsByTagName" return arrays, so you might want to add the index like this
getElementsByTagName('body')[0]
document.getElementsByClassName('someClassName')[1]
...
If it's still the 1990s where you are and jQuery hasn't been invented, then sure:
<div onclick="myFunc">
</div>
First you must find the element on the page, for example var element = document.getElementById('clickme'), then you must add a listener to the click event element.addEventListener('click',function)
I have created a label element. I need to add onclick event to that...
function a(me) {
var d=document.createElement("label");
d.id=me.id;
d.onClick="a(10)";
d.innerHTML="welcome";
document.body.appendChild(d);
}
HTML:
<label id="1" onclick="a(this)">aa</label>
<label id="2" onclick="a(this)">bb</label>
<label id="3" onclick="a(this)">aa</label>
actually what happens is when i click the any of three labels in html. another label is created and displays welcome. now when i click the newly created label "welcome" it does not display anything...... that is the onclick event added to newly created label is not working ....... any suggestion.................
You need to set d.onclick=function(){a(1);};, note that the case matters here (not "onClick").
[Edit]
Based on your comments and updated questions I've created a jsFiddle to demonstrate how you might turn your code into something that works.
d.setAttribute('onclick', 'alert(\'hello\');');
For creating an attribute to a HTML tag, sometimes we have to add this:
yourTag.src
yourTag.src = 'http://lolxd.com/404.png'
But there are special attributes, and them have diferents ways for editing:
yourTag.classList
yourTag.className
And there is the onclick attribute, wichwe can use it like this:
// The first way
obj.onclick = function () { alert('lalala') }
// With the Event Listener
obj.addEventListener('click', function () { alert('lalala') }, false)
// Or, a text-render way
obj.setAttribute('onclick', 'alert(`lalala`)')
I recomend you the Event Listener way, but try all :D