I'm trying to do a drag&drop directive which works with HTML5 dragging and also with mobile TouchEvents.
On Angular2 I have the dragstart event on which I can set the DragImage which works fine for me. But I think I don't have the same thing for TouchEvent touchstart so I'm not sure how to implement it.
In my opinion the only solution I have is to add DOM Element dynamically to directive.
So if this is the only way to do it my question is, how can i copy the ELEMENT where i attached the directive and copy it into DOM, on the right of the originally?
constructor(private elemRef: ElementRef, private renderer: Renderer) {
I can inject ElementRef and Renderer where elemRef.nativeElement is my DOM. But how can I copy this and add it to my component or Directive?
Related
I am using a javascript library that will add/remove elements to the DOM when some data is updated.
To add a new element to the DOM it calls a template function returning an element. In my case, the template function is defined inside an angular directive and returns something like return $compile(html)(scope)[0]; because I need to use the UI Bootstrap Popover directive inside the added element.
For the Popover, I need to use popover-append-to-body="true".
My problem is, if the triggering element is removed from the DOM, the popover is never removed. So if we add a new triggering element, a second popover will be appended to body, etc.
Here is a simplified example : http://plnkr.co/edit/AFsXBcaLBAs0F2garbAu?p=preview
Clicking on the "Click" button opens the popover, clicking "Remove" removes the "Click" button, clicking "Add" re-adds the "Click" button and clicking "Click" again adds a second popover to the DOM.
How can I remove the Popover directive when the triggering element is removed from the DOM ?
I need to totally deletes it, not only hide it/remove it from the DOM (I can hide it with popover-is-open but when this is set back to true, I see the popover still exists).
Is there a way to call destroy on the Popover directive of the element that will be deleted ?
You shouldn't do DOM manipulation in you a controller, both in JS and HTML, that's why directives are for, and for your case there were a couple of built in directives you could have used.
you should have kept an array to represent your buttons and popover states
you should place all you JS code in your controller, and used ng-click to bind click events to functions in your controller
don't use onclick when you have ng-click
The angular API works completely different then vanilla JS and even jquery, so don't mix them, use what Angular provides you, refer to the docs for help.
Here is your "revamped" code
I am trying to add a modal button to a leaflet map legend, with a AngularJS framework. Check out the map and modal buttons in this demo (modal buttons are the round info buttons): http://skyplan.ch/maps/dev/gwm6/
The modals are inserted using an Angular directive that looks like <div infomodal="views/modals/popup.html">.
I need to place such a button in the map legend. The problem is that since the legend is created dynamically, I need to $compile the modal directive. However, I only have access to the the content of the map control via the onAdd function of the control iControl.
I have tried calling $compile on the div that is generated in the onAdd function, but that hasn't worked. Has anybody tried to do something like this before?
I got it using the following steps:
Got the scope of your main controller in a variable.
var scope = angular.element('[ng-controller]:first').scope();
Created a custom button to test change of the language
var $div = $('<div><button ng-click="lang=\'de\';changeLanguage();">Change Language to DE</button></div>');
Appended it to your leaf legend control
$('.leaflet-bottom.leaflet-right:last .leaflet-control').append($div);
Force the angular to compile the appended the HTML control specifying the scope context of your main controller (1st step)
angular.injector(['ng']).invoke(function($compile) {
$compile($div)(scope);
});
Click the button and the "magic" happens. :-)
You may need to append (step 3) and recompile (step 4) after each MapBox update.
Since I was outside your project, that was the steps necessary to achieve the solution, but once your have the directive logic (not ugglified) you have full access to the leafpanel thru the $element and the $compile using directive service injection.
I'm trying to create an animation for an element that is initially hidden by a ng-show="boolDefaultIsFalse" attribute.
When I trigger the boolean to be true then the element is shown, but the animation doesn't play.
This is because the element never gets the ng-show class. It does start with a ng-hide class. But as soon as I show the element then that class is removed and no new ones are added.
Here's a demo of my problem: http://plnkr.co/edit/OkJnxKlp9Ym1mc8CCD05
Anyone any idea how to solve this problem?
Update
I've updated the Plunker.
I added the ng-class directive to add the ng-show class manually to the div. But the animation still doesn't play.
When you include ngAnimate as a dependency of your module:
var app = angular('app', ['ngAnimate']);
Angular will automatically add/remove the following CSS classes when the ng-show/ng-hide directives are applied:
ng-hide-add
ng-hide-add-active
ng-hide-remove
ng-hide-remove-active
To take advantage of this, add your CSS animation styles to these classes.
Here is an Demo
From the angular documents for ng-show:
The element is shown or hidden by removing or adding the ng-hide CSS class onto the element.
If you want to dynamically add / remove a class, you should use ng-class.
I have an AngularJS directive that binds to the scroll event:
angular.element($window).bind('scroll',function()
{
});
It's used to update the class of a fixed element when it reaches the bottom of the page.
The problem I have is that when a function fires new elements are drawn and the page grows longer. When scrolling again this is detected properly and the element updates it's class correctly, but until the scroll event fires it looks wrong.
Is there a way to bind the directive to also fire when new elements are drawn to the DOM as well as to scroll?
How are new elements added to the dom? There's multiple ways to attack this depending on how. Let's say their being rendered via an ng-repeat. For each element attach a new directive (via class, attribute, etc....) and then in the directives controller fire the event you require. Something like:
<div data-ng-repeat="item in items" class="myDirectiveName">...</div>
Then in your directive:
.directive("myDirectiveName", function(){
return {
restrict: 'C',
link: function(scope){
//fire event
scope.$emit("newElementAdded", element);
}
};
})
edit
If you only want it to fire on the last one, you can do a check
link: function(scope){
if(scope.$last){
...
}
}
Ng-repeats come with a few things attached to their scopes that you can use, $last, $first etc... check it out here: https://docs.angularjs.org/api/ng/directive/ngRepeat
Directly listening to events with bind(or on) will not cause a digest cycle in angular. You will need to call $apply on the scope to make sure all watchers are called.
Also, depending on if you add the elements manually to the DOM you will need to use the $compile service to have angular parse and execute all directives in the elements.
I have an application that contains a div with content in it. When I click a button jQuery adds a AngularJs directive to the div. After adding the directive i call scope.$apply(), but this doesn't seem to inform angular about the new directive on the div. Can someone explain to me how I can inform AngularJs about the new directive added with jQuery?
You shouldn't be adding directives to your markup with JQuery. Use Angular for that whenever possible.
That said, if you have to add directives via straight DOM manipulations like that, you'll need to use the $compile provider to compile the element and bind it to a scope before you add it.