2013-02-13 9 views
27

Wie kann ich eine Direktive mit einer dynamischen Vorlage erstellen? AngularJS - Richtlinientemplate dynamisch

'use strict'; 

app.directive('ngFormField', function($compile) { 
return { 
    transclude: true, 
    scope: { 
     label: '@' 
    }, 
    template: '<label for="user_email">{{label}}</label>', 
    // append 
    replace: true, 
    // attribute restriction 
    restrict: 'E', 
    // linking method 
    link: function($scope, element, attrs) { 
     switch (attrs['type']) { 
      case "text": 
       // append input field to "template" 
      case "select": 
       // append select dropdown to "template" 
     } 
    } 
    } 
}); 
<ng-form-field label="First Name" type="text"></ng-form-field> 

Das ist, was ich jetzt haben, und es wird das Etikett richtig angezeigt. Ich bin mir jedoch nicht sicher, wie ich der Vorlage zusätzlichen HTML-Code hinzufügen kann. Oder kombinieren 2 Vorlagen in 1.

Antwort

16

Hatte ein ähnliches Bedürfnis. $compile macht den Job. (Nicht ganz sicher, ob dies der "Weg" ist, der immer noch meinen Weg durch den Winkel geht)

http://jsbin.com/ebuhuv/7/edit - mein Explorationstest.

Eine Sache zu beachten (per meinem Beispiel), eine meiner Anforderungen war, dass die Vorlage basierend auf einem type Attribut geändert wurde, sobald Sie auf Speichern geklickt haben, und die Vorlagen waren sehr unterschiedlich. Wenn Sie also eine neue Vorlage benötigen, müssen Sie die Datei neu kompilieren.

+0

Es scheint nicht, Ihr Beispiel ordnungsgemäß funktioniert. Könnten Sie nachverfolgen? – cdnicoll

+0

Edit: Hat es funktioniert, sieht aus wie es Bootstrap war. Aktualisierter Link: http://jsbin.com/wikocaru/2/edit – cdnicoll

+2

Die Antworten sollten vollständige Beispiele und Code enthalten, nicht Links, die später als defekte Links enden. – swenedo

28

Ich habe den $ templateCache verwendet, um etwas Ähnliches zu erreichen. ich habe mehrere ng-templates in eine html-datei geschrieben, die ich mit der templateUrl der direktive referenziere. Dadurch wird sichergestellt, dass der HTML-Code für den Vorlagencache verfügbar ist. Dann kann ich einfach per ID auswählen, um die gewünschte ng-Vorlage zu erhalten.

template.html:

<script type="text/ng-template" id=“foo”> 
foo 
</script> 

<script type="text/ng-template" id=“bar”> 
bar 
</script> 

Richtlinie:

myapp.directive(‘foobardirective’, ['$compile', '$templateCache', function ($compile, $templateCache) { 

    var getTemplate = function(data) { 
     // use data to determine which template to use 
     var templateid = 'foo'; 
     var template = $templateCache.get(templateid); 
     return template; 
    } 

    return { 
     templateUrl: 'views/partials/template.html', 
     scope: {data: '='}, 
     restrict: 'E', 
     link: function(scope, element) { 
      var template = getTemplate(scope.data); 

      element.html(template); 
      $compile(element.contents())(scope); 
     } 
    }; 
}]); 
+3

Schöner Zug, Zim! Nur eine kleine Vereinfachung: $ templateCache ist in der Link-Funktion verfügbar, so dass Sie die getTemplate-Funktion nicht wirklich benötigen. –

+0

@zim Aber wie würden Sie id dynamisch übergeben? – NeiL

+0

+1 für '$ compile (element.contents())'. War verrückt geworden, weil ich nichts über diese '.contents()' in' $ compile' wusste. (Endlosschleife, die natürlich meine Direktive aufruft) –

1

gelang es mir, mit diesem Problem fertig zu werden. Unten ist der Link:

https://github.com/nakosung/ng-dynamic-template-example

mit den spezifischen Datei Wesen:

https://github.com/nakosung/ng-dynamic-template-example/blob/master/src/main.coffee

dynamicTemplate Richtlinie hosts dynamische Vorlage, die in Umfang und gehostete Element wie andere einheimische Winkelelemente wirkt übergeben wird.

scope.template = '< div ng-controller="SomeUberCtrl">rocks< /div>' 
8

Sie sollten Ihren Schalter in die Vorlage bewegen, indem Sie die "ng-switch Richtlinie:

module.directive('testForm', function() { 
    return { 
     restrict: 'E', 
     controllerAs: 'form', 
     controller: function ($scope) { 
      console.log("Form controller initialization"); 
      var self = this; 
      this.fields = {}; 
      this.addField = function(field) { 
       console.log("New field: ", field); 
       self.fields[field.name] = field; 
      }; 
     } 
    } 
}); 

module.directive('formField', function() { 
    return { 
     require: "^testForm", 
     template: 
      '<div ng-switch="field.fieldType">' + 
      ' <span>{{title}}:</span>' + 
      ' <input' + 
      '  ng-switch-when="text"' + 
      '  name="{{field.name}}"' + 
      '  type="text"' + 
      '  ng-model="field.value"' + 
      ' />' + 
      ' <select' + 
      '  ng-switch-when="select"' + 
      '  name="{{field.name}}"' + 
      '  ng-model="field.value"' + 
      '  ng-options="option for option in options">' + 
      '  <option value=""></option>' + 
      ' </select>' + 
      '</div>', 
     restrict: 'E', 
     replace: true, 
     scope: { 
      fieldType: "@", 
      title: "@", 
      name: "@", 
      value: "@", 
      options: "=", 
     }, 
     link: function($scope, $element, $attrs, form) { 
      $scope.field = $scope; 
      form.addField($scope); 
     } 
    }; 
}); 

Es Gebrauch wie das sein kann:

<test-form> 
    <div> 
     User '{{!form.fields.email.value}}' will be a {{!form.fields.role.value}} 
    </div> 
    <form-field title="Email" name="email" field-type="text" value="[email protected]"></form-field> 
    <form-field title="Role" name="role" field-type="select" options="['Cook', 'Eater']"></form-field> 
    <form-field title="Sex" name="sex" field-type="select" options="['Awesome', 'So-so', 'awful']"></form-field> 
</test-form> 
2

Wenn Sie AngularJS verwenden möchten Richtlinie mit dynamischer Vorlage, können Sie diese Antworten verwenden, aber hier ist mehr professionelle und legal Syntax davon. Sie können TemplateUrl nicht nur mit Einzelwert verwenden. Sie können es als eine Funktion verwenden, die einen Wert als URL zurückgibt. Diese Funktion hat einige Argumente, die Sie verwenden können.

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html

+0

Dies ermöglicht keine dynamische Änderung des Inhalts, wenn sich einige Daten ändern. Zum Beispiel war ich ein Datentyp-Attribut, um die zu verwendende Vorlage zu diktieren - wenn der Benutzer den Typ wechselt, brauche ich eine andere Vorlage. – mjaggard

0

Ich habe in der gleichen Situation gewesen, meine Komplettlösunghere

Grundsätzlich gebucht wurde ich auf diese Weise nach einer Vorlage in der Richtlinie laden

var tpl = '' + 
    <div ng-if="maxLength" 
     ng-include="\'length.tpl.html\'"> 
    </div>' + 
    '<div ng-if="required" 
     ng-include="\'required.tpl.html\'"> 
    </div>'; 

dann auf den Wert maxLength und required kann ich dynamisch eine der 2 Vorlagen laden, von denen jeweils nur eine angezeigt wird Falls benötigt.

Ich hoffe es hilft.

2

Eine Möglichkeit, eine Template-Funktion in Ihrer Richtlinie verwendet:

... 
template: function(tElem, tAttrs){ 
    return '<div ng-include="' + tAttrs.template + '" />'; 
} 
... 
Verwandte Themen