2016-03-25 5 views
3

は私の指示角度で要素クリックを効率的に検出する方法は?私たちが見ることができるようにここで

function linkFunc(scope, element, attr){ 

     // Detect Element Click Logic 
     scope.myCtrl.clickedElsewhere = {value: true}; 

     $document.on('click', function(){ 
      scope.myCtrl.clickedElsewhere.value = true; 
      scope.$apply(); 
     }); 

     element.on('click', function(){ 
      event.stopPropagation(); 
      scope.myCtrl.clickedElsewhere.value = false; 
      scope.$apply(); 
     }); 
     // End Detect Element Click Logic 

    } 

のための私のリンク機能で、私たちは、これは、すべてのドキュメント内の任意の場所をクリックするために、我々はダイジェスト・サイクルをトリガすることを意味し、$document.on()scope.applyを使用しました。 $watchトリガーが多い場合は、Webページが遅くなる可能性があります。この実装はすべて効率的ではありませんが、エレメントのクリックとオフの要素をクリックして検出する他の方法を考えて、エレメントの拡張と縮小を考えることはできません。

誰かが洞察力を与えてくれますか?

おかげ

+3

あなたは 'ng-click'を使います。 – Casey

+0

@Casey Hmm、しかし、私はどのように収縮の要素のクリックを検出するでしょうか?私はクリックしたときにリストを拡張する必要がありますが、ユーザーが他の要素をクリックしたときにはリストを縮小します。 ng-clickは要素のクリックでのみ検出されるようです。 – testing

+0

なぜドキュメントごとに '$ scope.apply()'を実行する必要がありますか? – charlietfl

答えて

3

それはに多く、より効率的になりますドキュメントのクリックハンドラで$apply()を呼び出す前にscope.myCtrl.clickedElsewhere.valueにチェックしてください。

$document.on('click', function(){ 
    if(!scope.myCtrl.clickedElsewhere.value){ 
     scope.myCtrl.clickedElsewhere.value = true; 
     scope.$apply(); 
    } 
}); 

これにより、状態が変化しても不要なダイジェストが防止されます。


あなたが要素をクリックしたとき

また、このクリックリスナーを削除し、それを再適用することができます:

function docHandler() { 
    if (!scope.myCtrl.clickedElsewhere.value) { 
    scope.myCtrl.clickedElsewhere.value = true; 
    scope.$apply(); 
    $document.off('click');//remove event listener completely 
    } 
} 

element.on('click', function() { 
    event.stopPropagation(); 
    scope.myCtrl.clickedElsewhere.value = false; 
    scope.$apply(); 
    $document.on('click', docHandler);// add document listener 
}); 
+0

簡単な質問ですが、 '.off'は' document'の 'click'リスナーを登録した他のディレクティブに影響を与えますか? – testing

+0

はい...jQueryを使用しているようですので、 '$ document.on( 'click.someClickName' ...'と '$ document.off( 'click.someClickName')'のような名前空間のイベントリスナーも使用できます。影響を受けた – charlietfl

+0

それを指摘してくれてありがとう、ありがとう – testing

0

あなたはそれらの間の親/子関係で、2つのディレクティブを作成することができます。

私が作成したアコーディオン指令を見てください。あなたの状況を把握するために必要なものだと私は信じています。

ディレクティブ:

app.directive("accordion", function() { 
    return { 
     template: "<div ng-transclude></div>", 
     restrict: "E", 
     scope: { 
      closeall: "@" 
     }, 
     transclude: true, 
     replace: true, 
     controller: function ($scope, $element, $attrs) { 
      var itensScope = []; 

      var addItemScope = function (scope) { 
       itensScope.push(scope); 
      }; 

      var closeItens = function() { 
       if ($scope.closeall == "false") return; 
       angular.forEach(itensScope, function (scope) { 
        scope.showItem = false; 
       }); 
      } 
      return { 
       addItemScope: addItemScope, 
       closeItens: closeItens 
      }; 
     } 
    }; 
}); 
app.directive("accordionItem", function() { 
    return { 
     template: "<div><div class='item' ng-class='{itemClose: !showItem}'>{{title}}</div><div class='itemInformation' ng-show='showItem' ng-transclude></div></div>", 
     restrict: "E", 
     transclude: true, 
     replace: true, 
     scope: { 
      title: "@" 
     }, 
     require: "^accordion", 
     link: function (scope, element, attrs, ctrl, transcludeFn) { 
      ctrl.addItemScope(scope); 
      element.bind("click", function() { 
       ctrl.closeItens(); 
       scope.$apply(function() { 
        scope.showItem = !scope.showItem; 
       }); 
      }); 
     } 
    }; 
}); 

使用法:

<accordion closeall="true"> 
     <accordion-item title="A"> 
      <p> 
       A 
      </p> 
     </accordion-item> 
     <accordion-item title="B"> 
      <p> 
       B 
      </p> 
     </accordion-item> 
</accordion> 

私はしばらく前にこの例を作成し、それは私のGitHubで提供されています:https://github.com/rodrigobranas/branas-angular-ui

2

あなただけのオフクリックディレクティブを作成することができ

myApp.directive('clickOff', function($parse, $document) { 
    var dir = { 
    compile: function($element, attr) { 
     // Parse the expression to be executed 
     // whenever someone clicks _off_ this element. 
     var fn = $parse(attr["clickOff"]); 
     return function(scope, element, attr) { 
     // add a click handler to the element that 
     // stops the event propagation. 
     element.bind("click", function(event) { 
      event.stopPropagation(); 
     }); 
     angular.element($document[0].body).bind("click",function(event) { 
      scope.$apply(function() { 
       fn(scope, {$event:event}); 
      }); 
     }); 
     }; 
    } 
    }; 
    return dir; 
}); 

使用法:

<div ng-app="myApp"> 
    <button ng-click="show=true;" click-off="show=false;"> 
     Click Me 
    </button> 
    <div class="message" ng-show="show" ng-init="show = false"> 
    You clicked on the button. Now click anywhere else... 
    </div> 
</div> 

例: https://jsfiddle.net/oytdwyxj/

+0

これは私にはるかに角度を感じます。 – Casey

関連する問題