2012-07-28 8 views
25

¿Es posible de alguna manera usar ngTransclude para un valor de atributo, en lugar de reemplazar el contenido HTML interno? Por ejemplo este sencillo Directiva¿Cómo puedo transcribir en un atributo?

var testapp = angular.module('testapp', []) 

testapp.directive('tag', function() { 
    return { 
    template: '<h1><a href="{{transcludeHere}}" ng-transclude></a></h1>', 
    restrict: 'E', 
    transclude: true 
    } 
}); 

y utilizarlo como

<tag>foo</tag> 

quiero que se traduce en

<h1><a href="foo">foo</a></h1> 

¿Hay alguna manera de hacer eso, o tengo que usar un atributo en lugar de transclusión?

Aquí hay una fiddle con el ejemplo

Respuesta

24

Algo como esto:

var testapp = angular.module('testapp', []) 

testapp.directive('tag', function() { 
    return { 
    restrict: 'E', 
    template: '<h1><a href="{{transcluded_content}}">{{transcluded_content}}</a></h1>', 
    replace: true, 
    transclude: true, 
    compile: function compile(tElement, tAttrs, transclude) { 
     return { 
      pre: function(scope) { 
       transclude(scope, function(clone) { 
        scope.transcluded_content = clone[0].textContent; 
       }); 
      } 
     } 
    } 
    } 
});​ 

fiddle.

7

Una solución más:

app.directive('tag', function($compile) { 
    return { 
    restrict: 'E', 
    template:"<h1></h1>", 
    transclude: 'element', 
    replace: true, 
    controller: function($scope, $element, $transclude) { 
     $transclude(function(clone) { 
     var a = angular.element('<a>'); 
     a.attr('href', clone.text()); 
     a.text(clone.text());   
     // If you wish to use ng directives in your <a> 
     // it should be compiled 
     //a.attr('ng-click', "click()"); 
     //$compile(a)($scope);  
     $element.append(a); 
     }); 
    } 
    }; 
}); 

Plunker: http://plnkr.co/edit/0ZfeLz?p=preview

+2

Esta sería una mejor respuesta si no tuviera manipulación DOM dentro del controlador – georgiosd

+0

Sí, usar '$ element' es generalmente una mala idea. – mgol

+2

@georgiosd -> DOM manipulación es exactamente lo que hace la directiva ngTransclude. –

2

respuesta de Vadim se puede fijar fácilmente mediante el uso de la función compile, y devolver la función postLink, donde tranclusion sucederá.

app.directive('tag', function ($compile) { 
    return { 
    restrict: 'E', 
    template: '<h1></h1>', 
    transclude: 'element', 
    replace: true, 
    compile: function($element, $attrs) { 
     return function ($scope, $element, $attrs, $controller, $transclude) { 
      $transclude(function(clone) { 
      var a = angular.element('<a></a>'); 
      a.attr('href', clone.text()); 
      a.text(clone.text());   
      // If you wish to use ng directives in your <a> 
      // it should be compiled 
      // a.attr('ng-click', 'click()'); 
      // $compile(a)($scope); 
      $element.append(a); 
      }); 
     }; 
    } 
    }; 
}); 

favor refiérase a https://docs.angularjs.org/api/ng/service/ $ compilar

La función $transclude solía ser aprobada en la función compile, pero se desaprobó, y ahora está en la función link.

4

Sé originalmente que su pregunta era acerca de la transclusión, pero este problema es MUCHO más sucintamente resuelto usando un atributo.

var testapp = angular.module('testapp', []) 

testapp.directive('tag', function() { 
    return { 
    template: '<h1><a href="{{url}}">{{url}}</a></h1>', 
    restrict: 'E', 
    scope: { 
     url: '@' 
    } 
    } 
}); 

y su html

<tag url="foo"></tag> 

La traducción:

<h1><a href="foo">foo</a></h1> 

Además, con la última versión de angular, hay una característica llamada "vinculante de una sola vez", es decir perfecto para situaciones como esta en las que solo desea/necesita cumplir el valor interpolado una vez, tras la inicialización. La sintaxis es la siguiente:

{{::url}} 

simplemente reemplazar todas las instancias de {{url}} en su plantilla con lo anterior.

Cuestiones relacionadas