Различные ng-include на одной странице: как отправлять разные переменные каждому?
У меня есть страница в моем приложении AngularJS, в котором я хотел бы включить один и тот же html файл, но с разными переменными. Если я сделаю это в своем главном html
:
<div id="div1" ng-include src="partials/toBeIncluded.html onload="var='A'">
<div id="div2" ng-include src="partials/toBeIncluded.html onload="var='B'">
И toBeIncluded.html
выглядит как
<div>{{var}}</div>
Оба div
будут выглядеть как
<div id="div1"><div>B</div></div>
<div id="div2"><div>B</div></div>
Я предполагаю, что это связано с тем, что тот же самый onload
вызывается для al-ng-includes. Итак, как мне отправлять разные переменные для каждого из них?
Ответы
Ответ 1
Выражение, переданное в onload
, оценивается каждый раз при загрузке новой частичной части. В этом случае вы дважды меняете значения var
, поэтому к тому времени, когда будут загружены обе частичные данные, текущее значение будет B
Вы хотите передать разные данные каждому частичному/шаблону (при этом базовый html файл будет таким же). Чтобы достичь этого, как упоминает Тиаго, вы можете сделать это с помощью разных контроллеров. Например, рассмотрим следующие
<body ng-controller='MainCtrl'>
<div ng-include src='"toBeIncluded.html"' ng-controller='ctrlA' onload="hi()"></div>
<div ng-include src='"toBeIncluded.html"' ng-controller='ctrlB' onload="hi()"></div>
</body>
Здесь у нас есть две частичные части, каждая из которых имеет свою собственную область действия, управляемую их собственным контроллером (ctrlA
и ctrlB
), как для дочерних областей MainCtrl
. Функция hi()
принадлежит области MainCtrl
и будет выполняться дважды.
Если у нас есть следующие контроллеры
app.controller('MainCtrl', function($scope) {
$scope.msg = "Hello from main controller";
$scope.hi= function(){console.log('hi');};
});
app.controller('ctrlA', function($scope) {
$scope.v = "Hello from controller A";
});
app.controller('ctrlB', function($scope) {
$scope.v = "Hello from controller B";
});
И содержимое toBeIncluded.html
<p>value of msg = {{msg}}</p>
<p>value of v = {{v}} </p>
Получаемый html будет состоять из следующих строк
<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from main controller A </p>
и
<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from controller B </p>
Пример здесь: http://plnkr.co/edit/xeloFM?p=preview
Ответ 2
Точно так же, как сказал Марк, но чтобы немного упростить его и сделать более "на лету", нужно использовать следующее:
<div ng-repeat="name in ['John']" ng-include="'name-template.html'"></div>
<div ng-repeat="name in ['Jack']" ng-include="'name-template.html'"></div>
<script type="text/ng-template" id="name-template.html">
<div>The name is {{ name }}</div>
<script>
Пример здесь: http://jsfiddle.net/Cndc6/4/
Ответ 3
В своем комментарии к @jm- answer вы указываете, что хотите загрузить частичный внутри ng-repeat. Для этого создайте массив в своей области $scope и задайте уникальные значения в этом массиве:
$scope.partialStuff = [ 'p1', 'p2', 'p3' ];
Где-то в частичном:
{{partialVar}}
HTML:
<div ng-repeat="partialVar in partialStuff">
<div ng-include src="'partials/toBeIncluded.html'"></div>
</div>
Fiddle.
Ответ 4
Я мог ошибаться, но лучше ли было бы использовать директиву?
.directive('foobar', [function factory() {
return {
restrict: 'E',
replace: true,
templateUrl: '/toBeIncluded.html',
scope: {
"var": "="
}
};
}]);
И ваш HTML
<div ng-repeat="var in data">
<foobar var="var"></foobar>
</div>
Теперь элемент foobar должен быть заменен вашим шаблоном. Каждый из них имеет свой собственный охват.
Ответ 5
В частности, выражения ng-init и onload оцениваются в области parent, а не в области дочерних объектов, созданной nginclude. Таким образом, вы дважды назначаете значения var
в родительской области, оба из которых происходят до того, как содержимое внутри этих ng-включений загружается скомпилированным и оцененным. Когда создается каждая дочерняя область, она наследует родительскую область, где var = 'B'.
Ответ 6
считают, что у вас есть переменная foo внутри вашего частичного,
то вы пройдете foo следующим образом:
<ng-include src="'partials/foo-part.html'" onLoad="foo='bar'"></ng-include>
для большей совместимости с браузером вы можете передать это следующим образом:
<div ng-include src="'partials/foo-part.html'" onLoad="foo='bar'"></div>
вы также можете использовать onInclude="foo='bar'"
вместо onLoad
plnkr.co/edit/GHRNyAMBKLvgtf3NFSRu?p=info
Ответ 7
Тот же "onLoad" не вызывается для всех ng-includes. Скорее всего, var установлен в A, а затем на B. Дело в том, что он разделяется между обоими включениями, потому что они находятся в одной области. 'var ', как модель в угловом JS, зависит от объема.
Чтобы ваши частичные части имели отдельные значения, у каждого из них должны быть свои собственные области. Самый простой способ сделать это можно было бы установить контроллер или директиву и назначить его элементу Dom, где находится ng-include, и установить значение в пределах этой области.
Ответ 8
У меня была такая же проблема, и я нашел способ добиться того, что хотел
конечно, это выглядит не очень красиво, но все же.
Я использовал ng-repeat, который создаст новую область для включения одного и того же шаблона дважды с разными значениями, подобными этому (фиктивный пример):
<script type="text/ng-template" id="mod-edito.html">
<div class="mod-edito__media">
<img ng-src="{{ edito.cover.src }}" />
</div>
</script>
<div>
<ng-include ng-repeat="edito in [edito_object]" src="'mod-edito.html'"></ng-include>
...
<ng-include ng-repeat="edito in [edito_other]" src="'mod-edito.html'"></ng-include>
</div>
Это приемлемо? Я так думаю.
Ответ 9
Я искал альтернативу, я хотел, чтобы объект js отправил несколько параметров во включенную часть. Это развитая версия того, что сделал @denis-pshenov. Вы можете использовать контроллер для заполнения данных или ng-init.
В принципе, что-то вроде этого,
var myApp = angular.module('myApp',[]);
myApp.controller('Controller', function($scope) {
$scope.ourData = [ { name : 'John', address : 'Paradise' } ];
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="Controller">
<div ng-repeat="data in ourData" ng-include="'partial.html'"></div>
<div ng-init="ourData2 = [ { name : 'Jack', address : 'Paradise' } ]" />
<div ng-repeat="data in ourData2" ng-include="'partial.html'"></div>
</div>
<script type="text/ng-template" id="partial.html">
<div>The name is {{ data.name }} and the address is {{ data.address }} </div>
</script>
Ответ 10
Существует способ создания универсальной директивы многократного использования.
Вот что мой коллега придумал (вдохновленный Knockout.js).
Директива
(function () {
'use strict';
angular
.module('directives')
.directive('ngWith', ngWith);
function ngWith() {
return {
restrict: 'A',
replace: true,
scope: {
model: '=',
template: '@'
},
template: '<div data-ng-include="template"></div>',
};
}
})();
Использование:
<div data-ng-with="" data-model="parentObj.childObj.whatEver" data-template='my-template.html'></div>
Ответ 11
Просто голова, если вы включите частичное в ng-repeat, вы все равно можете получить доступ к родительскому объекту $index. Просто включите {{$ index}} в частичное.
Ответ 12
Использование onload не является чистым решением, поскольку оно помещает глобальную область. Если у вас есть что-то более сложное, оно начнет сбой.
Использование новой директивы вместо ng-include является более чистым решением.
Идеальное использование выглядит следующим образом:
<div ng-include-template="partials/toBeIncluded.html" ng-include-variables="{ var: 'A' }"></div>
<div ng-include-template="partials/toBeIncluded.html" ng-include-variables="{ var: 'B' }"></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 и добавляет эти члены в свою собственную локальную область.
ng-include не является повторным, поскольку он имеет доступ к глобальной области. Это немного странно.
Надеюсь, это то, что вам хотелось бы; он чистый и общий.
Ответ 13
Вы можете обратиться к функциям одиночных значений типа $scope.a = 'test'
и для объектов типа $scope.a = {a.test};
и использовать разную область для определения области видимости.
Из документации ng-if.
Обратите внимание, что при удалении элемента с помощью ngIf его область уничтожается и создается новая область, когда элемент восстанавливается.
Решение Simpe состоит в том, чтобы включить ng-if
и определить статическую контентификацию в директиве ng-init
.
<div ng-if="<any-true-expression>" ng-init="val='First'" ng-include="'html/common.html'"</div>
<div ng-if="<any-true-expression>" ng-init="val='Second'" ng-include="'html/common.html'"</div>
В этом случае он будет отображаться с различными значениями, например
{{val}} shows >>
First
Second
Этот контент является статическим, поскольку val является ссылкой simpe на значение.
Если вы хотите иметь динамически изменяемые страницы, которые зависят от некоторых общих значений области, вам необходимо уничтожить и воссоздать область действия, созданную при использовании директивы ng-if
. Вот так:
<div id="wrapper" ng-if="orders_client">
<div id="client-orders" ng-init="orders = orders_client" ng-include="'html/pages/parts/orders-view.html'"></div>
</div>
и
$scope.orders_client = null;
/*recreate content table*/
$timeout(function () {
$rootScope.general.showPreloader = false;
$scope.orders_client = $scope.baseData.clients[newClient];
}, 500);
В этом случае область с ранее данными будет уничтожена, и будет создана новая область с новыми данными. Необходимо время для воссоздания новой области 500 мс. Пожалуйста, напишите, если существует какой-то лучший улов.
Ответ 14
Просто поместите каждый ng-include под свой собственный <div>
следующим образом:
<div>
<div id="div1" ng-include src="partials/toBeIncluded.html onload="var='A'"/>
</div>
<div>
<div id="div2" ng-include src="partials/toBeIncluded.html onload="var='B'"/>
</div>
Каждый включенный HTML будет иметь свой собственный var
в своей области.