2017-04-27 78 views
13

我试图建立一个指令,将做到以下几点:

  • 添加其他指令元素(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,它的工作原理如下。

有没有人知道背后的原因是什么 - 如果我能使它工作?

或者如果有人对如何实现我上面所述的另一个想法?

+0

以'NG-show'作品更换任何'NG-if's的。不知道为什么会发生。 – koox00

+0

是的,但我需要ng-if :) – sirrocco

+0

@sirrocco参考指令的'compile'函数中的代码:为什么您要手动编译元素?如果删除编译函数中的最后三行只有'el.removeAttr('swipe');'它按预期工作 –

回答

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

工作对我来说... 而且一点是,在你的代码 - 你马上编译元素指令编译,而在这里的功能是由编译返回,将somewhen后执行。

0

考虑一下。 ngIf删除整个元素并将其替换为注释。然后观察表达式。随后的更改触发DOM到REMOVED之间的元素。

现在的问题是,你已经把块放在编译阶段。整个ng-if的代码被替换为单个注释。

关于解决方案,可以有很多。这一切都取决于结构和需求,如果你的应用程序很好。

我提出两种:

1)从 '编译' 到 '链接' 相移的逻辑。

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

2)您将需要使用transclusion。

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

希望它能帮助。

1

由于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>