Angular – How can I remove from the DOM an element I have used $compile on?

All we need is an easy explanation of the problem, so here it is.

What I need is the functionality of two ng-views. Because I can’t I want to change the innerHTML of something and compile it. The problem I have is when I change the content again, I can compile, but does angular remove the binding on it’s own, or I do I have to do it manually, if so, how?

EDIT: Explaining

I want to make a modal, whose content I can change and bind to different scopes (hence the $compile). But I don’t want to destroy the whole modal, just some of its content, and change to another. My main doubt is if by removing some compiled HTML it can lead to memory leaks.

SOLVED

For this problem, I created a new child scope (with $new) and destroyed it whenever I changed the content.
Thanks for everything

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

To manually remove the element do an element.remove(). Sounds like you also want to destroy the scope of your compiled element so you can do that too by doing scope.$destroy(); or $scope.$destroy(); depending on if you’re in a directive or not.

http://docs.angularjs.org/api/ng.$rootScope.Scope#$destroy

Method 2

Thanks for you good solution. I’ve just posted some implement code

.directive('modal', function($templateCache, $compile) {
    return function(scope, element, attrs) {
        var currentModalId = attrs.modalId;
        var templateHtml = $templateCache.get(attrs.template);
        var modalScope, modalElement;

        scope.$on('modal:open', function(event, modalId) {
            if(modalId == null || currentModalId === modalId) {
                openModal();
            }
        });

        scope.$on('modal:close', function(event, modalId) {
            if(modalId == null || currentModalId === modalId) {
                closeModal();
            }
        });

        function openModal() {
            // always use raw template to prevent ng-repeat directive change previous layout
            modalElement = $(templateHtml);

            // create new inherited scope every time open modal
            modalScope = scope.$new(false);

            // link template to new inherited scope of modal
            $compile(modalElement)(modalScope);

            modalElement.on('hidden.bs.modal', function() {
                if(modalScope != null) {
                    // destroy scope of modal every time close modal
                    modalScope.$destroy();
                }
                modalElement.remove();
            });

            modalElement.modal({
                show: true,
                backdrop: 'static'
            });
        }

        function closeModal() {
            if(modalElement != null) {
                modalElement.modal('hide');
            }
        }
    };
});

Method 3

The solution for this problem is creating a new child scope. All bindings with parent scope work because of scope Inheritance. When I need to change the content, I simply destroy the child scope, avoiding memory leaks.

I’ve also made and getter and setter methods for the child scope to avoid poluting que parent scope, in case the other content uses disposable variables

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply