2012-07-28 13 views
25

È possibile utilizzare in qualche modo ngTransclude per un valore di attributo, invece di sostituire il contenuto HTML interno? Per esempio questo semplice direttivaCome posso effettuare una transazione in un attributo?

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

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

e usarlo come

<tag>foo</tag> 

voglio che si traducono in

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

C'è un modo di fare che, o devo usare un attributo invece di transientare?

Ecco un fiddle con l'esempio

risposta

24

Qualcosa di simile a questo:

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

più Una soluzione:

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

Questa sarebbe una risposta migliore se non avesse la manipolazione DOM all'interno del controller – georgiosd

+0

Sì, usare '$ element' è in genere una cattiva idea. – mgol

+2

@georgiosd -> La manipolazione DOM è esattamente ciò che fa la direttiva ngTransclude stessa. –

2

risposta di Vadim può essere facilmente risolto utilizzando la funzione compile, e restituendo la funzione postLink, dove tranclusion accadrà.

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); 
      }); 
     }; 
    } 
    }; 
}); 

prega di fare riferimento al https://docs.angularjs.org/api/ng/service/ $ compilare

La funzione $transclude utilizzato per essere passato nella funzione compile, ma è stato sconsigliato, ed è ora nella funzione link.

4

In origine so che la tua domanda riguardava la transclusione, ma questo problema è MOLTO più risolto in modo succinto usando un attributo.

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

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

e il vostro html

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

La traduzione:

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

Inoltre, con la versione più recente di angolare, v'è una funzione denominata "vincolante di una volta" che è perfetto per situazioni come questa in cui si desidera/deve soddisfare il valore interpolato una sola volta, al momento dell'inizializzazione. La sintassi è simile al seguente:

{{::url}} 

semplicemente sostituire tutte le istanze di {{url}} nel tuo modello con quanto sopra.

Problemi correlati