1

I am trying to simplify the code below, which is inside angular controller, dynamically adds attribute and recompiles directive inner html.

additionalInfo: '=',

This attribute enables parts of the code in a template, so it must be recompiled while being dynamically created

$element.attr('additional-info', "'test'");
var template = angular.element('<a></a>').append($element.clone()).html();
$element.replaceWith($compile(template)($scope.$parent));

The code works fine, I am trying to distill the code to minimum, any thoughts? Maybe something can be replaced to look nicer?

I have got two more options, which yield the same result:

var template = angular.element('<a></a>').append($element.clone()).html();
var template = $element.get(0).outerHTML;
var template = $element.html($element.get(0).cloneNode(true));

All of them work correctly, but the last one is actually returning an object, but this still works? How? Why? Pros/Cons?

4
  • For the love of God and all that is holy never manipulate the DOM in a controller, ever! For more information as to why see: docs.angularjs.org/guide/controller Commented Jan 24, 2015 at 22:15
  • 1
    @Enzey Yep, I was told to make custom directives for DOM manipulation and that is what I have been doing ever since :) Commented Jan 24, 2015 at 22:19
  • Your question states that you are adding attributes as part of the controller. Is this being done as part of a function on the controller that takes in the element and changes it? Commented Jan 24, 2015 at 22:22
  • @Enzey yes, the code receives data in controller and performs recompilation, but how is that related to simplifying DOM code? Commented Jan 24, 2015 at 23:01

1 Answer 1

1

First off why are you recompiling the elements in the DOM? I ask as there is likely a better solution.

Secondly, both of the solutions you propose do not work. Yes, they appear to give you the same results as what was displayed however if you were using two-way binding you lost that can cannot get it back.

Such that once <div>{{value}}</div> is resolved it will forever be the resolved values <div>SomeValue</div>.

To recompile the code exactally as it was then you need to precompiled DOM, which is only available in a directives compile function. You would need to store off that uncompiled HTML and when something occurs change it and rebuild it.

.directive('someDirective', function() {
    return {
        compile: function($element, $attrs) {
            var originalHtml = $element[0].outerHTML;
            return: function(scope, element, attrs) {
                // some action occurs
                var newElement = angular.element(originalHtml);
                element[0].insertBefore(newElement, element[0].parent);
                $compile(newElement)(scope);
            };
        }
    }
})
Sign up to request clarification or add additional context in comments.

2 Comments

The initial question still stands, why are you doing this? Recompiling the DOM works but it is very unperformant and will not scale well. You have shown that you already have something but are asking us which of the very costly rendering options is better to use. I am trying to find out if there is a better option that what you have already proposed.
I want to dynamically add an attribute to the directive and force update of template rules, thats what my test shows

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.