Как внедрить html-тег из базы данных в шаблон моей директивы, фактически динамически определяя корневой элемент/тег шаблона?

Я хочу динамически создать шаблон с данными из базы данных (в моем случае Firebase/angularFire). Способ построения шаблона зависит от свойства тега в каждом объекте, полученном с помощью angularFire. Мой первый подход:

var imgTemplate = function(tag){
  return '<'+tag.tag+' class="{{ tag.classes }}" src="{{ tag.content }}" alt="{{ tag.alt }}">';
};
var txtTemplate = function(tag){
  return '<'+tag.tag+' class="{{ tag.classes }}">{{ tag.content }}</'+tag.tag+'>';
};

Это почти работает, но tag.tag не определен вместо фактического тега, что понятно, поскольку функция компиляции, которая использует эти функции, будет запущена до того, как angularFire извлечет и привяжет данные. Вот мой второй подход:

var imgTemplate = function(tag){
  return '<{{tag.tag}} class="{{ tag.classes }}" src="{{ tag.content }}" alt="{{ tag.alt }}">';
};
var txtTemplate = function(tag){
  return '<{{ tag.tag }} class="{{ tag.classes }}">{{ tag.content }}</{{ tag.tag }}>';
};

Но это многократно отображает только часть буквальной строки txtTemplate:

<{{ tag.tag }} class="{{ tag.classes }}">{{ tag.content }}

для каждого элемента тега, повторяемого с помощью ng-repeat вместо фактического html.

Это функция компиляции моей директивы:

  compile: function(templateElem, directiveAttrs){
    var tag = directiveAttrs.tag;
    if(tag.tag === 'img'){
      var img = angular.element(imgTemplate(tag));
      templateElem.replaceWith(img);
    }else{
      var txt = angular.element(txtTemplate(tag));
      templateElem.replaceWith(txt);
    }
  },

данные извлекаются из Firebase в контроллере состояния angular.ui.router:

.state("siteNav.sideNav.content", {
  url: '/:lang/:view/:contentID/:index',
  views:{
    '@': {
      templateUrl: '/views/content.html',
      controller: function($scope, angularFire){
        var stateParams = $scope.$stateParams;
        console.log(stateParams.lang);
        var url = 'https://example.firebaseio.com/'+stateParams.lang+'/content/'+stateParams.view+'/'+stateParams.contentID;
        angularFire(new Firebase(url), $scope, 'tags');
      }
    }
  }
}

А шаблон content.html выглядит так:

<div ng-repeat="tag in tags">
  <acms-view tag="tag"></acms-view>
</div>
  • Мне нужна трехсторонняя привязка, предлагаемая angularFire.
  • Тег должен быть получен из базы данных firebase, вместо него нельзя использовать литерал (в окончательной версии этот тег может быть чем угодно).

Как я могу гарантировать, что свойство 'tag' будет заполнено до того, как функция компиляции использует его для сравнения/присваивания значения?
Невозможно использовать службу angularFire в функции компиляции, так как нет области для привязки извлеченных данных.
По какой-то причине angularFire не работает в функции связывания, хотя даже если бы он работал, я не думаю, что это сильно помогло бы, так как мне все еще нужно построить шаблон.
Должен ли я использовать Firebase js api в функции компиляции вместо angularFire?
Если да, то как мне заставить работать трехстороннюю привязку, которую предлагает angularFire?
Спасибо за ваше время
Джаред


person Jared Tomaszewski    schedule 11.09.2013    source источник


Ответы (1)


Вы можете создать обещание, используя $q и установив $scope.tags в качестве обещания, которое вернет данные, когда angularFire получит их. Например:

.state("siteNav.sideNav.content", {
  url: '/:lang/:view/:contentID/:index',
  views:{
    '@': {
      templateUrl: '/views/content.html',
      controller: function($scope, $q, angularFire){
        var stateParams = $scope.$stateParams;
        var url = 'https://example.firebaseio.com/'+stateParams.lang+'/conten /'+stateParams.view+'/'+stateParams.contentID;
        var deferred = $q.defer();
        $scope.tags = deferred.promise;
        angularFire(new Firebase(url), $scope, 'rawTags').then(function() {
          deferred.resolve($scope.rawTags);
        });
      }
    }
  }
}
person Anant    schedule 11.09.2013