Как указать модель в директиву ngInclude в AngularJS?
Я хотел бы использовать один и тот же шаблон HTML в трех местах, каждый раз с другой моделью.
Я знаю, что могу получить доступ к переменным из шаблона, но имена будут разными.
Есть ли способ передать модель в ngInclude?
Это то, чего я хотел бы достичь, конечно, переменная add-variable теперь не работает. Затем в моем включенном шаблоне я получаю доступ к объектам detailsObject и его свойствам.
<pane title="{{projectSummary.ProjectResults.DisplayName}}">
<h2>{{projectSummary.ProjectResults.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" init-variable="{'detailsObject': projectSummary.ProjectResults}"></ng-include>
</pane>
<pane title="Documents" header="true"></pane>
<pane ng-repeat="document in projectSummary.DocumentResults" title="{{document.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': document}"></ng-include>
</pane>
<pane ng-repeat="header in [1]" title="Languages" header="true"></pane>
<pane ng-repeat="language in projectSummary.ResultsByLanguagePairs" title="{{language.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': language}"></ng-include>
</pane>
Если я использовал плохой подход с использованием ng-include, есть ли что-то еще, что я должен попробовать?
Ответы
Ответ 1
ПРИМЕЧАНИЕ. Это не мой первоначальный ответ, но так я сделал бы это после использования angular для бит.
Я бы создал директиву с шаблоном html как разметку, передаваемую динамическими данными в директиву, как показано в этой скрипке.
Шаги/примечания для этого примера:
- Определите директиву с разметкой в
templateUrl
и атрибутах (ах), используемых для передачи данных в директиву (с именем type
в этом примере).
- Используйте данные директивы в шаблоне (с именем
type
в этом примере).
- При использовании директивы в разметке убедитесь, что вы передали данные из области контроллера в директиву (
<address-form type="billing"></address-form>
(где биллинг обращается к объекту в области контроллера).
- Обратите внимание, что при определении директивы имя является верблюжьим, но при использовании в разметке оно ограничено нижним регистром (т.е. оно называется
addressForm
в js, но address-form
в html). Подробнее об этом можно узнать в angular docs здесь.
Вот js:
var myApp = angular.module('myApp',[]);
angular.module('myApp').directive('addressForm', function() {
return {
restrict: 'E',
templateUrl: 'partials/addressform.html', // markup for template
scope: {
type: '=' // allows data to be passed into directive from controller scope
}
};
});
angular.module('myApp').controller('MyCtrl', function($scope) {
// sample objects in the controller scope that gets passed to the directive
$scope.billing = { type: 'billing type', value: 'abc' };
$scope.delivery = { type: 'delivery type', value: 'def' };
});
С разметкой:
<div ng-controller="MyCtrl">
<address-form type="billing"></address-form>
<address-form type="delivery"></address-form>
</div>
ОРИГИНАЛЬНЫЙ ОТВЕТ (который полностью отличается от директивы BTW).
Примечание. Скрипка из моего первоначального ответа ниже не работает больше из-за ошибки (но сохраняя ее здесь, если она по-прежнему полезна)
Об этой дискуссии в группе Google вы говорили здесь.
Похоже, что эта функциональность не поддерживается из коробки, но вы можете использовать патч Brice, как описано в этом сообщении.
Вот пример кода из jsfiddle:
<script id="partials/addressform.html" type="text/ng-template">
partial of type {{type}}<br>
</script>
<div ng-controller="MyCtrl">
<ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
<ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
</div>
Ответ 2
Существует довольно простое решение, хотя я должен признать, что это не то, что Мишко рекомендовал бы. Но если создание директивы является излишним для вас и получение патча Brice нецелесообразно, то следующее поможет вам.
<div ng-repeat="name in ['A']" ng-include="'partial.html'"></div>
<div ng-repeat="name in ['B']" ng-include="'partial.html'"></div>
<script type="text/ng-template" id="partial.html">
<div>{{ name }}</div>
</script>
Совершенно очевидно, почему это работает. См. Пример здесь: http://jsfiddle.net/Cndc6/4/
Ответ 3
Есть повод, чтобы исправить это, но похоже, что он мертв:
https://github.com/angular/angular.js/pull/1227
Не изменяя исходный код Angular, это решит проблему в режиме многократного использования, не слишком хэкетирующем:
directive('newScope', function() {
return {
scope: true,
priority: 450,
};
});
И пример:
<div new-scope ng-init="myVar = 'one instance'" ng-include="'template.html'"></div>
<div new-scope ng-init="myVar = 'another instance'" ng-include="'template.html'"></div>
Вот его плунжер в действии:
http://plnkr.co/edit/El8bIm8ta97MNRglfl3n
Ответ 4
Решение Quick'n'dirty:
<div ng-init="details=document||language||projectSummary.ProjectResults">
Ответ 5
<div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>
directive('newScope', function () {
return {
scope: true,
priority: 450,
compile: function () {
return {
pre: function (scope, element, attrs) {
scope.$eval(attrs.newScope);
}
};
}
};
});
Это директива, объединяющая new-scope
from ответ Джона Кулвинера с кодом от Angular ng-init
.
Для полноты, это Angular 1.2 26 ng-init source, вы можете увидеть единственное изменение в новой области директива - это добавление scope: true
{
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit);
}
};
}
}
Ответ 6
Я тебя слышу! ng-include не является повторным, поскольку он имеет доступ к глобальной области. Это немного странно.
Должен быть способ установить локальные переменные. Использование новой директивы вместо ng-include является более чистым решением.
Идеальное использование выглядит следующим образом:
<div ng-include-template="'Partials/SummaryDetails.html'" ng-include-variables="{ 'detailsObject': language }"></div>
Директива:
.directive(
'ngIncludeTemplate'
() ->
{
templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
restrict: 'A'
scope: {
'ngIncludeVariables': '&'
}
link: (scope, elem, attrs) ->
vars = scope.ngIncludeVariables()
for key, value of vars
scope[key] = value
}
)
Вы можете видеть, что директива не использует глобальную область действия. Вместо этого он считывает объект из ng-include-variables и добавляет эти члены в свою собственную локальную область.
Он чистый и общий.