diwatu
diwatu

Reputation: 5699

element.replaceWith in a custom directive's link only work at first time called

I am new to Angularjs, and don't understand too much behind the scene. Basically I want to create an 'E' kink directive, base on the data in controller I dynamically create the html, like a whole 'table' thing, to replace the directive.

The directve in my html file is like this:

<matrixrows></matrixrows>

My directive code is like this:

angular.module('matrix', [.....])
.directive('matrixrows', [..., function (...) {
        return {
            restrict: 'E',
            replace: true,
            require: '^matrix',
            link: function (scope, element, attr, ctrl) {
                ......... 
                scope.$watch('currentPage', function (newValue, oldValue) {
                    if (newValue && newValue != oldValue) {

                        var html = "";
                        .......................
                        here is the code to generate the html
                        .......................
                        element.replaceWith(html);
                    }
                });
             }
    }])

Through watching currentPage's change I recreate the html and replace the directive tag. When the first time I change 'currentPage', the element.replaceWith(html) works fine. Then I change 'currentPage angin, the watching function will be triggered, but the element.replaceWith(html) won't work.

Then I stepped into Angularjs source code, I found, after the first time element.replaceWith's execution, element[0].parentNode became null, this caused the replaceWith crash.

Anybody know how to make it work?

Upvotes: 9

Views: 3849

Answers (2)

david marcus
david marcus

Reputation: 183

You should be using $compile(...) on the generated html string.

ex:

    link: function (scope, element, attr, ctrl) {
        ......... 
        var currentElement = element;
        scope.$watch('currentPage', function (newValue, oldValue) {
            if (newValue && newValue != oldValue) {
                .......................
                var html = "";
                here is the code to generate the html
                .......................
                var replacementElement = $compile(html)(scope);
                currentElement.replaceWith(replacementElement);
                currentElement = replacementElement;
            }
        });
     }

Upvotes: 2

Gaute L&#248;ken
Gaute L&#248;ken

Reputation: 7892

It looks like you're attempting to replace the same element several times. But once it's been replaced, it's gone. To solve this store the currentHtml in a variable. Something like this:

        link: function (scope, element, attr, ctrl) {
            ......... 
            var currentElement = element;
            scope.$watch('currentPage', function (newValue, oldValue) {
                if (newValue && newValue != oldValue) {
                    .......................
                    var html = "";
                    here is the code to generate the html
                    .......................
                    var replacementElement = angular.element(html);
                    currentElement.replaceWith(replacementElement);
                    currentElement = replacementElement;
                }
            });
         }

Upvotes: 12

Related Questions