Подтвердить что ты не робот

Weird ngIf + $компилирование

Я пытаюсь создать директиву, которая будет делать следующее:

  • добавить другую директиву в элемент (например, ngSwipeRight)
  • добавить новое поведение в новую директиву.

В качестве примера можно привести: mySwipeBack, который добавил бы ngSwipeRight, и когда пользователь проведет над элементом, я сделаю history.back().

Я пробовал вот так:

.directive('swipe', function($compile){
  return {
    restrict: 'A',
    compile: function(el){
        // I removed all the actual logic for demo purposes
        // here I would add ng-swipe-right plus a handler
        el.removeAttr('swipe');
        var fn = $compile(el);
        return function (scope) {
          fn(scope);
        };
   }
 }
});

Но я столкнулся с проблемой со следующей разметкой:

<div ng-if='true'>
  <h1 swipe>OUTSIDE
    <div ng-if="true">INSIDE</div>
  </h1>
</div>

Текст "ВНУТРИ" не отображается. Вы можете увидеть поведение в этом jsbin: http://jsbin.com/tokofevuga/edit?html,js,output

Если я удалю первый ng-if, он работает по назначению.

Кто-нибудь знает, в чем причина этого, и если я могу заставить его работать?

Или, если у кого-то есть другое представление о том, как достичь того, что я описал выше?

4b9b3361

Ответ 1

    return function (scope) {
      $compile(el)(scope);
    };

Работайте для меня... И дело в том, что в вашем коде - вы компилируете элемент сразу в компиляции директивы, тогда как функция возвращается из компиляции, которая будет выполнена позже.

Ответ 2

Так как ng-if создает свой собственный scope, я думаю, что вы просто скомпилируете элемент слишком рано.

В приведенном ниже фрагменте кода я переместил compile part в link и связал элемент с текущей областью самой директивы.

var app = angular.module('jsbin', []);

app.controller('DemoCtrl', function() {

});

app.directive('swipe', function($compile) {
  return {
    restrict: 'A',
    link: function($scope, el) {
      el.removeAttr('swipe');
      $compile(el)($scope);
    }
  }
});
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Angular JS</title>
</head>

<body ng-app="jsbin">
  <div ng-controller="DemoCtrl">
    <div ng-if='true'>
      <h1 swipe>OUTSIDE
        <div ng-if="true">INSIDE</div>
      </h1>
    </div>
  </div>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.js"></script>
</body>

</html>

Ответ 3

Рассмотрим это. ngIf удаляет весь элемент и заменяет его комментарием. Затем выражение отслеживается. Последующие изменения активируют элемент между DOM и REMOVED.

Теперь проблема в том, что вы поместили блок в фазу компиляции. Код для всего ng-if заменяется одним комментарием.

В отношении решения может быть много. Все зависит от того, что хорошо соответствует структуре и потребностям, если ваше приложение.

Я предлагаю два:

1) Переместите логику с "компиляции" на фазу "link".

link: function(el){
    el.removeAttr('swipe');
    var fn = $compile(el);
    return function (scope) {
      fn(scope);
    };
 },

2) Вам нужно будет использовать переход.

app.directive('swipe', function($compile){
 return {
  restrict: 'A',
  compile: function(el){
    el.removeAttr('swipe');
    var fn = $compile(el);
    return function (scope) {
      fn(scope);
        };
   },
    transclude: true,
    template: "<div ng-transclude></div>"
 }
});

Следующие вилки вашего образца могут вам помочь:

http://jsbin.com/zecujonoqi/1/edit?html,js,output

http://jsbin.com/mubodevofa/1/edit?html,js,output

Надеюсь, что это поможет.