Компиляция динамического 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. То есть визуализировать каждый шаблон с изолированными данными области. Нужно обобщить директиву.



Любая помощь ценится! Заранее спасибо.

551   2  

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

    Ничего не найдено.