最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS: element.show() in directive not working - Stack Overflow

programmeradmin2浏览0评论

I have a directive (see plunk) that wraps a DIV with style display:none and after one second shows its content. I tried to make it display with element.show() and $(element).show() (including jQuery) but it never worked. The timeout works, what's wrong with this code?

This is the HTML:

    <hideme>
      Show this after one second
    </hideme>

and this is the javascript:

angular.module("app", []);

function MyCtrl($scope) {}

angular.module("app").directive('hideme', function($timeout) {

    return {

        restrict: 'E',
        template: '<div style="display: none !important"></div>',
        link: function(scope, element, attrs) { 
            $timeout(function() {
                  element.show();
            }, 1000);
        }
   };
});

I have a directive (see plunk) that wraps a DIV with style display:none and after one second shows its content. I tried to make it display with element.show() and $(element).show() (including jQuery) but it never worked. The timeout works, what's wrong with this code?

This is the HTML:

    <hideme>
      Show this after one second
    </hideme>

and this is the javascript:

angular.module("app", []);

function MyCtrl($scope) {}

angular.module("app").directive('hideme', function($timeout) {

    return {

        restrict: 'E',
        template: '<div style="display: none !important"></div>',
        link: function(scope, element, attrs) { 
            $timeout(function() {
                  element.show();
            }, 1000);
        }
   };
});
Share Improve this question edited Dec 2, 2014 at 9:38 7stud 48.6k14 gold badges106 silver badges134 bronze badges asked Dec 2, 2014 at 2:12 ps0604ps0604 1,07126 gold badges150 silver badges370 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 4

The element is shown, the problem is that it does not contain anything to show. Also, to have the show function, you need to add a jQuery dependency and apply it to the correct div.

angular.module("app", []);

function MyCtrl($scope) {}

angular.module("app").directive('hideme', function($timeout) {
  return {
    restrict: 'E',
    transclude: true,
    template: '<div style="display: none;"><div ng-transclude></div></div>',
    link: function(scope, element, attrs) {
      $timeout(function() {
        element.find("div:hidden").show();
      }, 1000)
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <hideme>
    Show me after one second.
  </hideme>
</div>

That said. I would do it this way:

angular.module("app", []).directive('hideme', function($timeout) {
  return {
    restrict: 'E',
    transclude: true,
    scope: true,
    template: '<div ng-show="show"><div ng-transclude></div></div>',
    link: function(scope, element, attrs) {
      scope.show = false;
      $timeout(function() {
        scope.show = true;
      }, 1000)
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <hideme>
    Show me after one second.
  </hideme>
</div>

  1. The template gets inserted into your custom tag, so your <div> becomes a child of the <hideme> tag.

  2. In the link() function, the element argument is the <hideme> tag--not the <div>--therefore unhiding the <hideme> tag does not unhide a child <div> which has been styled with display: none. In other words, if you have this:

    <hideme style="display: block"> <div style="display: none">Show this in three seconds.</div> </hideme>

    that won't display the <div>.

  3. If you don't load jQuery before loading angularjs, then angularjs uses something it calls jqLite to wrap elements. The wrapped elements act like jQuery wrapped sets, but they have reduced functionality, e.g. show() and hide() are not provided.

So if you load jQuery and then load angularjs, you can do this:

app.js:

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

app.directive('hideMe', ['$timeout', function($timeout) {
  var directive = {};

  directive.restrict = 'E';

  directive.link = function(scope, element, attrs) {
    element.html(
      '<div style="display:none">' 
      + element.text() 
      + '</div>'
    );

    $timeout(function() {
      element.children().show();
    }, 3000);

  };


  return directive;
}]);

index.html:

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

<head>
  <!-- For html5 (default is UTF-8) -->
  <meta charaset="UTF-8">
  <!-- For Bootstrap -->
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>AngularJS Examples</title>

  <!-- Bootstrap CSS -->
  <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
  <!-- app.css -->
  <link href="app.css" rel="stylesheet">

</head>

<body class="container">

   <hide-me>Show this after three seconds.</hide-me>



<!-- JQuery 2.1.1 -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Angular 1.3.3 -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>

<!-- app.js -->
<script src="app.js"></script>

</body>
</html>

However, I notice that the text flashes briefly on the page before being hidden. Edit: If I replace element.text() with element.html(), then there's no flash.

On the other hand, if you don't load jQuery you can do this:

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

app.directive('hideMe', ['$timeout', function($timeout) {
  var directive = {};

  directive.restrict = 'E';

  directive.link = function(scope, element, attrs) {
    var hideme = element[0];
    hideme.innerHTML = '<div style="display:none">' + hideme.innerHTML + '</div>';

    $timeout(function() {
      var div = hideme.childNodes[0];
      div.style.display = "block";
    }, 3000);

  };


  return directive;
}]);

Then the text doesn't flash on the screen before being hidden.

.hide() and .show() functions work only if jquery is inserted before angular in your html file.

Gwenn

You could easily just use the following without including jQuery to show the element:

element.css('display', 'block');

And corresponding to hide it:

element.css('display', 'none');

Plunker: http://plnkr.co/edit/bzhCwjXdll3ibxc7qsMY?p=preview

Try using transclude:true and then ng-transclude to display the markup between custom element tags. Also, I'm not familiar with using show(), so instead set html ng-show='showEl' and define showEl = true in the timeout.

angular.module("app", []);

function MyCtrl($scope) {}

angular.module("app").directive('hideme', function($timeout) {

    return {
          transclude: true,
        restrict: 'E',
        template: '<div ng-show="showEl"><div ng-transclude></div></div>',
        link: function(scope, element, attrs) { 
            $timeout(function() {
                  scope.showEl = true;
              }, 1000);
        }
    };
});
发布评论

评论列表(0)

  1. 暂无评论