2013-02-13 10 views
27

Как создать директиву с динамическим шаблоном?AngularJS - шаблон шаблона директивы

'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> 

Это то, что я прямо сейчас, и он правильно отображает метку. Тем не менее, я не уверен, как добавить дополнительный HTML к шаблону. Или объединение 2 шаблонов в 1.

ответ

16

Имел аналогичную потребность. $compile выполняет эту работу. (Не совсем уверен, что это «способ» для этого, все еще работающий мой путь через угловой)

http://jsbin.com/ebuhuv/7/edit - мой тест на разведку.

Одно замечание (в моем примере), один из моих требований состоял в том, что шаблон изменился бы на основе атрибута type, как только вы нажмете на сохранение, и шаблоны были очень разными. Итак, вы получаете привязку данных, если вам нужен новый шаблон, вам придется перекомпилировать.

+0

ваш пример работает правильно. Не могли бы вы продолжить? – cdnicoll

+0

Редактировать: У меня это работает, похоже, что это был бутстрап. Обновленная ссылка: http://jsbin.com/wikocaru/2/edit – cdnicoll

+2

Ответы должны включать полные примеры и код, а не ссылки, которые в конечном итоге будут сломанными ссылками позже. – swenedo

28

Я использовал шаблон $ templateCache для выполнения чего-то подобного. Я поместил несколько ng-шаблонов в один html-файл, который я ссылаюсь на шаблон templateUrl. что гарантирует, что html доступен для кеша шаблона. то я могу просто выбрать по id, чтобы получить ng-шаблон, который я хочу.

template.html:

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

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

директива:

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

Хороший ход, Зим! Просто небольшое упрощение: $ templateCache доступен внутри функции ссылки, поэтому вам действительно не нужна функция getTemplate –

+0

@zim Но как бы вы прошли динамически? – NeiL

+0

+1 для '$ compile (element.contents())'. Сошел с ума, потому что я не знал об этом '.contents()' '' '' compile''. (конечно, цикл, называющий мою директиву) –

1

мне удалось справиться с этой проблемой. Ниже приводится ссылка:

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

с конкретным файловым бытием:

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

dynamicTemplate директива хосты динамического шаблон, который передается в пределах области и размещаются элемент действует, как и другие родные угловые элементы.

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

Вы должны переместить переключатель в шаблон с помощью 'ng-switch' директиву:

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

Это может быть использование так:

<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

Если вы хотите использовать AngularJs Директива с динамическим шаблоном, вы можете использовать эти ответы, но здесь больше профессионалов и legal синтаксис. Вы можете использовать templateUrl не только с одним значением. Вы можете использовать его как функцию, которая возвращает значение как url ​​. Эта функция имеет некоторые аргументы, которые вы можете использовать.

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

+0

Это не позволяет динамически изменять содержимое при изменении некоторых данных. Например, я был атрибутом типа данных, чтобы диктовать используемый шаблон - тогда, когда пользователь переключает тип, мне нужен другой шаблон. – mjaggard

0

Я был в такой же ситуации, мое полное решение была размещена here

В основном я загрузить шаблон в директиве таким образом

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

затем по до значения maxLength и required Я могу динамически загружать один из 2 шаблонов, показывается только один из них за раз если необходимо.

Я надеюсь, что это поможет.

2

Одним из способов является использование функции шаблона в вашей директиве: Это не похоже

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