Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve inner HTML of AngularJS directive before templateUrl overrides it

I have a directive I use for form validation boilerplate which I recently refactored. Allow me to explain the directive a little further before expanding.

The directive usage:

<form class="form-horizontal" name="personalDetails" validated-form>

    <!-- Pass buttons into form through here -->
    <a href="" class="btn btn-success" 
        data-ng-click="saveDetails()"
        data-ng-disabled="!personalDetails.$valid">Save Changes</a>

</form>

Previously, my directive looked something like this, and it worked.

app.directive('validatedForm', function($compile, $sce) {
    return {
        restrict: 'A',
        scope: true,
        link: function(scope, element, attrs) {

            var template = //... HTML boilerplate code
            var buttons  = element.html(); // Get contents of element before overriding

            element.html(template + buttons);
            $compile(element.contents())(scope);

        }
    }
});

The html template was becoming messy, and I wanted to wrap the buttons 'inside' of the template, rather than after them. So I refactored into what I thought was a much better directive.

app.directive('validatedForm', ['$compile', '$sce', function ($compile, $sce) {

    var domContent = null;

    return {
        restrict: 'AE',
        scope: true,
        templateUrl: '/Content/ngViews/directives/validated-form.html',
        link: function(scope, element, attrs) {

            // This now returns the contents of templateUrl 
            // instead of what the directive had as inner HTML
            domContent = element.html(); 

            // Scope
            scope.form = {
                caption: attrs.caption,
                location: 'Content/ngViews/forms/' + attrs.name + '.html',
                buttons: $sce.trustAsHtml(domContent),
                showButtons: !(domContent.replace(' ', '') === '')
            };

        }
    };
}]);

So what I'm noticing is that element.html() now retrieves the contents of the templateUrl instead of the contents of the inner HTML of my directive. How else can I get the contents of my directive before it gets overriden by the templateUrl?

like image 242
francisco.preller Avatar asked Nov 21 '13 01:11

francisco.preller


People also ask

What does $compile do in AngularJS?

Overview. Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together. The compilation is a process of walking the DOM tree and matching DOM elements to directives. Note: This document is an in-depth reference of all directive options.

What is attrs in AngularJS?

scope is an AngularJS scope object. element is the jqLite-wrapped element that this directive matches. attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values. controller is the directive's required controller instance(s) or its own controller (if any).

Which directive do we use to inform AngularJS about the parts controlled by it?

The ngRef attribute tells AngularJS to assign the controller of a component (or a directive) to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM element to the scope. The ngRepeat directive instantiates a template once per item from a collection.

What is restrict in AngularJS directive?

Restrict. Angular allows us to set a property named restrict on the object we return on our directive definition. We can pass through a string with certain letters letting Angular know how our directive can be used. function MyDirective() { return { restrict: 'E', template: '<div>Hello world!


1 Answers

To access the iniital html can use $transclude within directive controller. This is a slight change from earlier versions so assumes using 1.2

controller:function($scope,$transclude){
      $transclude(function(clone,scope){
        /* for demo am converting to html string*/
         $scope.buttons=angular.element('<div>').append(clone).html();
      });

    }

DEMO

like image 107
charlietfl Avatar answered Sep 22 '22 13:09

charlietfl