Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - Different template in directive

I have a form based on twitter bootstrap, each field have it's own configuration

// controller (the template shows this in ng-repeat

$scope.fields = [{name:"f1", label:"Field 1", with_button: false},
                 {name:"f2", label:"Field 2", with_button: true}]

I'm trying to make a "conditional directive" that customize the template according to "field.with_button"

// Without button
<div class="controls">
    <input type="text" id="i_{{field.name}}">
</div>

// With button
<div class="controls">
    <div class="input-append">
        <input type="text" id="i_{{field.name}}">
        <span class="add-on">bt</span>
    </div>
</div>

I searched a lot and didn't find any solution, I tried to create only one div and put contents inside with a compiler function but it didn't parse, and if I call $apply it crashes.

How could I make this directive?

wrong My last try:

angular.module('mymodule',[]).directive('ssField', function() {
    return {
        transclude:false,
        scope: {
            field: '='
        },
        restrict: 'E',
        replace:true,
        template: '<div class="controls">{{innerContent}}</div>',
        controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
            $scope.$eval('$scope.innerContent = \'<input type="text" id="input_{{field.name}}" placeholder="{{field.name}}" class="input-xlarge">\'');
        }]
    };
});

//<ss-field field="{{field}}"></ss-field>
like image 318
Giovanne Afonso Avatar asked May 04 '26 12:05

Giovanne Afonso


2 Answers

You can use the $http and $compile services to do what you're after.

http://plnkr.co/edit/Xt9khe?p=preview

This plnkr should demostrate what needs to be done, but basically:

  1. Use $http to load the template depending on the condition.
  2. Compile the loaded template against the current scope with $compile.
angular.module('mymodule',[]).directive('ssField', ['$http', '$compile', function($http, $compile) {
    return {
        transclude:false,
        scope: {
            field: '='
        },
        restrict: 'E',
        replace:true,
        template: '<div class="controls"></div>',
        link: function(scope, element, attrs) {
          var template;
          var withButtonTmpl = 'with_button.html';
          var withoutButtonTmpl = 'without_button.html';

          if (scope.field.with_button) {
            $http.get(withButtonTmpl).then(function(tmpl) {
              template = $compile(tmpl.data)(scope);
              element.append(template);
            });
          } else {
            $http.get(withoutButtonTmpl).then(function(tmpl) {
              template = $compile(tmpl.data)(scope);
              element.append(template);
            });
          }
        }
    };
}]);

You can change the directive to be more robust so the URLs aren't directly embedded in the directive for re-usability, etc., but the concept should be similar.

like image 180
Cuong Vo Avatar answered May 06 '26 01:05

Cuong Vo


Just to further expand on Cuing Vo's answer here is something similar to what I use(without using external partials and additional $http calls):

http://jsfiddle.net/LvUdQ/

myApp.directive('myDirective',['$compile', function($compile) {
    return {
        restrict: 'E',

        template: '<hr/>',
        link: function (scope, element, attrs, ngModelCtrl) {
            var template = {
                'templ1':'<div>Template 1</div>',
                'templ2':'<div>Template 2</div>',
                'default':'<div>Template Default</div>'
            };
            var templateObj;
            if(attrs.templateName){
                templateObj = $compile(template[attrs.templateName])(scope);
            }else{
                templateObj = $compile(template['default'])(scope);
            }
            element.append(templateObj);
        }    
    };
}]);

However Im not quite sure its by the bible from performance perspective.

like image 38
Tsonev Avatar answered May 06 '26 02:05

Tsonev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!