AngularJS: element.show () on directive not working
I have a directive ( see plunk ) that wraps a DIV with a style display:none
and shows its contents after one second. I tried to show it with element.show () and $ (element) .show () elements (including jQuery) but it never worked. Timeout is working, what is wrong with this code?
This is HTML:
<hideme>
Show this after one second
</hideme>
and this is 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);
}
};
});
source to share
Plunker: http://plnkr.co/edit/bzhCwjXdll3ibxc7qsMY?p=preview
Try using transclude: true and then ng-transclude to display markup between custom element tags. Also, I'm not familiar with using show (), so instead set html ng-show = 'showEl' and define showEl = true on 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);
}
};
});
source to share
The item is shown, the problem is that it does not contain anything to show. Also, to have a 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>
It said. I would do it like this:
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>
source to share
-
The template is inserted into your own tag, so yours
<div>
becomes a child of the tag<hideme>
. -
In the link () function, the argument
element
is a tag<hideme>
, not a tag<div>
, so displaying the tag<hideme>
does not display the child<div>
that was created withdisplay: none
. In other words, if you have this:<hideme style="display: block"> <div style="display: none">Show this in three seconds.</div> </hideme>
which does not display
<div>
. -
If you are not loading jQuery before loading angularjs then angularjs uses something that it calls jqLite to wrap the elements. Wrapped elements act like jQuery wrapped sets, but they have reduced functionality, eg. 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 noticed that the text flashes briefly on the page before disappearing. Edit: If I replace element.text()
with element.html()
then there is no flash.
On the other hand, if you are not loading 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 hiding.
source to share