There are a multiple questions here on how to bind Bootstrap popovers on dynamic elements, but none of them solves my issue.
At the moment I am initializing Popovers like this:
const popovers = this.element.querySelectorAll('[data-bs-toggle="popover"]')
const popoverTriggerList = [].slice.call(popovers)
popoverTriggerList.map(function (popoverTriggerEl: HTMLElement) {
return new Popover(popoverTriggerEl, {
container: popoverTriggerEl.parentElement as HTMLElement, // Render the popover next to the trigger element (needed when there are stimulus actions/targets inside the content which need to remain within the scope of the controller)
})
})
This however doesn't work for dynamically added elements on the page.
So, I'm trying the documented way to achieve this:
new Popover(document.body, {
selector: '[data-bs-toggle="popover"]',
// container: popoverTriggerEl.parentElement as HTMLElement, // How do I set that?
})
My problem is - Is there a way to make popovers render inside the parent element, not at the end of the body?
Related
I'm setting up an Ionic (4) app, where you can drag and drop elements from a toolbar into a window. I want to change the dropped elements depending on their types. I'm using ng2-dragula.
For exmaple I want to drop an element <ion-chip></ion-chip> and when it's dropped it should be something like <ion-card dragula="DRAGGABLE"></ion-card>.
-I tried changing the DOM outerHTML during an event ( https://github.com/valor-software/ng2-dragula/blob/master/modules/demo/src/app/examples/02-events.component.ts ), but then the dragula inside the new created element is not active.
-I tried *ngIf but this also seems not to load dynamically.
What other possibilities do I have?
<div dragula="DRAGULA_EVENTS">
<div>content</div>
</div>
BAG = "DRAGULA_EVENTS";
subs = new Subscription();
export class EventsComponent{
public constructor(private dragulaService: DragulaService){
this.subs.add(this.dragulaService.drop(this.BAG)
.subscribe(({el,source,target})=>{
el.outerHTML = "<ion-card dragula='DRAGULA_EVENTS'>content</ion-card>"
}
}
})
}
I expect that the new DOM element has the property dragula like i set it on the outerHTML-tag.
I figured it out (works during dragging or dropping):
Nest the dragula element in a new
Create inside page.component.ts :
this.subs.add(this.dragulaService.cloned(this.BAG).subscribe(({clone})=>{
Inside of this, with DOM methods, creating a new Element var new_El = document.createElement('ion-card')
Remove all Childs of the clone 'clone.removeChild(..)`
Bind the new Element inside the clone Element clone.appendChild(new_El)
I have a DOM element (say div), I am created a new element using javascript (specifically react), The new element is another div which is a sidebar.
The desired implementation is when the sidebar enters, the previous element shifts and the sidebar does not overlay
Do you mean something like this? Where the elements will move over based on the divs they are placed in?
$('button').toggle(
function() {
$('#B').css('left', '0')
}, function() {
$('#B').css('left', '200px')
})
Working example at:http://jsfiddle.net/hThGb/1/
Credit to:How to toggle (hide / show) sidebar div using jQuery
How can I add a class to element not if condition is true,
<div ng-class="{myClass: true/false}">
but if event is occurred. For example I have td, which displays some variable.
<td>{{myVar}}</td>//myVar=10
And when variable changed myVar=15 I add a constant class to div, which(class) don't depends on condition any more. Is it possible at all?
Try this in your angular controller. Note that i'm selecting all divs in HTML using querySelector while you should select the div as per your requirement
$scope.$watch('myVar', function() {
var myEl = angular.element(document.querySelector('div'));
myEl.addClass('myClass');
}, true);
I want to disable scrolling by default except for specific elements and their children in an AngularJS/Cordova hybrid application.
I don't want to introduce jQuery into the app so I am trying to use Angular's jqlite (the stripped down essentials of jQuery). I'm also open to using a directive to solve the problem if you have any suggestions.
As you can see below I'm using jqlite's parent() method to see if the element's parent has the scrollable class. However this is not effective because it would be better to check the element itself and any parents up the DOM tree. jQuery has a parents() method to do this but jqlite does not.
Any ideas how to use jqlite to check all parents of an element or how to get the desired solution from a directive?
// disable scrolling by default unless inside a `scrollable` element
document.addEventListener('touchmove', function (e) {
var scrollable = false;
// todo: need to go all the way up the DOM tree instead of just one level up
var items = angular.element(e.target).parent();
angular.forEach(items, function (o) {
var item = angular.element(o);
if (item.hasClass("scrollable")) {
scrollable = true;
}
});
if (!scrollable) {
e.preventDefault();
}
}, true);
Update: Everyone that contributed, it's well appreciated, you all are very kind and generous and all of you deserve my dear respect. Cheers.
Note: I'm making a simple jQuery tooltip plugin, the tooltip will fire on mouseover. The mouseover will create an instance of the div tool-tip that will be specific to each anchor that launched the div tool-tip. So each anchor with the class .c_tool will have its own created div that will erase after mouseout. Anyway all those details are irrelevant. What is important is how to create a div with .append() or .add() on and then find a way to call it and apply actions to that div without setting an identifier (id), class, or any means to identify it.
I know theres a way you could find the div by counting, so if you gave every created div the same class and then counted them to find that one, however I don't know if this is the most efficient method that is why I'm asking for help.
I'm not going to post the whole plugin script thats unnecessary, so I'll paste a simplified version.
hover me
hover me
$(document).ready(function() {
obj = $('a.c_tool');
obj.mouseover(function() {
/// append div to body it will be specific to each item with class c_tool, however I don't want to set an ID, or CLASS to the appended div
}).mouseout(function() {
/// remove added div without setting ID or class to it.
});
});
Working example:
http://jsfiddle.net/xzL6F/
$(document).ready(function() {
var tooltip;
obj = $('a.c_tool');
obj.mouseover(function() {
var element = $('<div>', {
html: "I'm a tooltip"
});
tooltip = element.appendTo($("body"));
/// append div to body it will be specific to each item with class c_tool, however I don't want to set an ID, or CLASS to the appended div
}).mouseout(function() {
tooltip.remove();
/// remove added div without setting ID or class to it.
});
});
To create a new DOM node you can use the jQuery constructor, like
$(document).ready(function() {
obj = $('a.c_tool');
obj.mouseover(function() {
if(!$.data(this, 'ref')) {
$.data(this, 'ref', $ref = $('<div>', {
html: 'Hello World!'
}).appendTo(document.body));
}
}).mouseout(function() {
$.data(this, 'ref').remove();
});
});
.appendTo() returns the DOM node of invocation (in this case, the newly created DIV) as jQuery object. That way you can store the reference in a variable for instance and access it later.
Referring your comment:
To remove all stored references, you should do this:
$('a.c_tool').each(function(index, node) {
$.removeData(node, 'ref');
});
you can use $.append(
);
http://api.jquery.com/append/
and to find the DOM created dynamically u can use
$("#dynamicallyCreatedDOMid").live("yourCustomTrigger",function(){
});
http://api.jquery.com/live/