None
None

Reputation: 9247

How to write directive to hide div clicking anywhere on page?

This is first time that I am writing directive. I am trying to write directive to hide my div.This is my html:

<div id="loggedIn" close-logged-in class="fade-show-hide"  ng-show="loggedInOpened" ng-cloak>
@Html.Partial("~/Views/Shared/_LoggedInPartial.cshtml")
</div>

I find element but when I click anywhere on page I dont get anything.Can someone help me how to write directive so that when shown user click anywhere on page, it will hide that div.Any suggestion?

'use strict';
    angular.module("accountModule").directive('closeLoggedIn', function () {
        return {
            scope: {},
            restrict: 'A',
            link: function (scope, element, attrs) {

                var loggedIn = angular.element(document.getElementById("loggedIn"));
                console.log(loggedIn);

                var isClosed = false;

                loggedIn.on('click', function (e) {

                    console.log("LOGGED IN ON CLICK ", loggedIn);

                });
            }
        }

I dont get this message "LOGGED IN ON CLICK"

Upvotes: 1

Views: 4225

Answers (1)

Matt Herbstritt
Matt Herbstritt

Reputation: 4862

You don't need getElementById("loggedIn") The <div> is already there for you as the element argument in the link function. There should rarely be any need to reference elements by their ID's in Angular.

Is this what you are trying to achieve?

DEMO

html

<div hide-when-click-anywhere default-display='block'>Click anywhere to hide me</div>

js

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

app.controller('MainCtrl', function($scope, $window) {
  $scope.isHidden = false;
});

app
.directive('hideWhenClickAnywhere', function ($window) {
  return {

    // bind a local scope (i.e. on link function scope) property 
    // to the value of default-display attribute in our target <div>.
    scope: {
      defaultDisplay: '@'
    },

    restrict: 'A',

    link: function (scope, element, attrs) {

      var el = element[0];

      // set default css display value. Use 'block' if 
      // the default-display attribute is undefined
      el.style.display = scope.defaultDisplay || 'block';  

      angular.element($window).bind('click', function(){

        // Toggle display value.
        // If you just want to hide the element and
        // that's it then remove this if block
        if(el.style.display === 'none'){
          el.style.display = scope.defaultDisplay || 'block';  
          return;
        }

        el.style.display = 'none';

      });
    } 

  };

});

Update

Ok after reading you comments I think this might be more what you're trying to achieve;

Take note of this line in the <button> element defined in template.html:

ng-click="contentHidden = !contentHidden; $event.stopPropagation();"

$event.stopPropagation() stops the event from bubbling up and triggering the 'click' listener we have defined on $window in our directive.

DEMO2

app.js

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

app.controller('MainCtrl', function($scope, $window) {
  $scope.hideOnStart = true;
});

app
.directive('panel', function ($window) {
  return {

    scope: {
      // this creates a new 'isolate' scope
      // '=' sets two-way binding between the directive 
      // scope and the parent scope
      // read more here https://docs.angularjs.org/api/ng/service/$compile
      hideOnStart: '=',
      panelTitle: '@'
    },

    transclude: true,
    templateUrl: 'template.html',

    restrict: 'E',

    link: function (scope, element, attrs) { 

      console.log(scope.panelTitle)

      // div content is hidden on start
      scope.contentHidden = scope.hideOnStart || false;

      angular.element($window).bind('click', function(e){

        // check if the content is already hidden
        // if true then ignore
        // if false hide the content
        if(!scope.contentHidden){
          scope.contentHidden = true;

          // we have to manually update the scope
          // because Angular does not know about this event
          scope.$digest();
        }

      });
    } 

  };

});

template.html

<div class="panel panel-default">

  <div class="panel-heading">

    <div class="panel-title">{{panelTitle}}
      <button 
        type="button" 
        class="close" 
        ng-click="contentHidden = !contentHidden; $event.stopPropagation();"
        aria-label="Close"
      >
        <span ng-hide="contentHidden">close</span>
        <span ng-hide="!contentHidden">open</span>
      </button>
    </div>

  </div>

  <div class="panel-body" ng-hide="contentHidden"  ng-transclude></div>

</div>

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl"> 

    <div class="container">
      <h1>Demo</h1>
      <div class="row">
        <div class="col-sm-6">
          <panel panel-title="Title" hide-on-start="hideOnStart">
            <h4>Content...</h4>
            <p>foo bar baz</p>
          </panel>
        </div>
      </div>
    </div>

  </body>

</html>

Upvotes: 3

Related Questions