Компиляция динамического HTML и привязка переменной из JSON response - директивы с изолированной областью видимости-AngularJS
Мне нужно отрисовать динамический шаблон из базы данных, а также привязать переменные к выражениям.
Мой ответ JSON будет выглядеть так,
[{
"htmlTemplate": "<div>{{name}}</div><div>{{age}}</div>",
"bindData": {
"name": "safeer",
"age" : "25"
}
}, {
"htmlTemplate": "<span>{{name}}</span><div>{{address}}</div>",
"bindData": {
"name": "john",
"address":"qwerty"
}
}, {
"htmlTemplate": "<h4>{{name}}</h4><h2>{{country}}</h2>",
"bindData": {
"name": "james",
"country":"India",
"state" : "Kerala"
}
}]
Я создал директиву в соответствии с ответом на вопрос компиляция динамических HTML строк из базы данных
В html, демо.html
<div dynamic="html"></div>
In директива, директива.js
var app = angular.module('app', []);
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
Он отобразит HTML-шаблон и заменит переменную переменной $scope переменной name тонко.
Но мне нужно отрисовать каждый htmlTemplate с соответствующими bindData. То есть визуализировать каждый шаблон с изолированными данными области. Нужно обобщить директиву.
Любая помощь ценится! Заранее спасибо.
2 ответов:
Когда вы получаете данные JSON, вы можете использовать
angular.fromJSONдля декодирования строки json в массив (если вы не используете $http.get () который уже делает это за вас)...//request the JSON from server jsonString = SomeFactory.fetchDataFromServer(); $scope.dataArray = angular.fromJson(jsonString);...а затем используйте
ngRepeatдля создания нескольких элементов:
<div ng-repeat="element in dataArray" dynamic="element"></div>Измените свою директиву следующим образом:
app.directive('dynamic', function ($compile) { return { restrict: 'A', replace: true, link: function (scope, ele, attrs) { scope.bindData = {}; scope.$watch(attrs.dynamic, function(dynamic) { console.log('Watch called'); ele.html(dynamic.htmlTemplate); //here's your htmlTemplate being compiled $compile(ele.contents())(scope); scope.bindData = dynamic.bindData; //here's your bound data ifyou need the reference scope.name = dynamic.bindData.name; //bound data property name }, true); //deep watch } }; });Edit: или вы можете просто передать
element.htmlTemplateиelement.bindDataотдельно директиве через два отдельных атрибута, как указано в ответе пользователя Vineet, что делает более чувство. Edit2: исправлены некоторые ошибки.Вот скрипка: Скрипка
С обобщением я предполагаю, что вы хотите сделать его как компонент и повторно использовать его, когда захотите.
Я бы предложил разделить сферу применения этой директивы. Свяжите свой "html" и "name" оба из них от родителя.ПОСЛЕ РЕДАКТИРОВАНИЯ:
app.directive('dynamic', function ($compile) { return { restrict: 'A', replace: true, scope : { html : "=dynamic" }, link: function (scope, ele, attrs) { ele.html(scope.html); $compile(ele.contents())(scope); var unbindWatcher = $scope.$watch( attrs.bindData, function(binddata) { if ( binddata ) { angular.extend(scope,binddata); // Once the data has been binded to scope, // there's no more need to watch the change // in the model value. unbindWatcher(); } } ); } }; });И ваш html как:
<div dynamic="html" bindData="bindData"></div>В этой правке я сделал следующие 3 вещи:
1) просмотр атрибута bindData - который будет содержать сохраненные в БД данные привязки. Я не включил это в сферу охвата директивы, потому что я хочу включить ее свойства в область видимости, чтобы вы могли связать свое " имя " и т. д. от bindData в БД к шаблонам.
2) расширение объекта bindData в область действия вашей директивы. Теперь ваша область будет иметь " имя " и т. д.
3)уничтожение наблюдателя, как только bindData будет прочитана в первый раз. Это гарантирует, что любое изменение переменной bindData внутри родительского элемента не будет передано директиве после первой привязки.
Но все же держите область действия разделенной чтобы заставить его работать должным образом.
Надеюсь, это решит вашу проблему
Comments