I'm filling in an array in angularJS using $http.get()
service, by calling a rest api. This array is displayed using ng-repeat
. There is Jquery code to display a button on hovering over each of the <li>
tags. $http
causes a delay in fetching the data, by which time Jquery would have finished binding. So the hover function doesn't work. Any work arounds for this?
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script src="angular.js"></script>
<script src="jquery.js"></script>
<script>
$(document).ready(function() {
myFunction();
});
var myFunction= function(){
$("#orders ul li").hover(
function() {
$(this ).find(".butt-view").show();
},
function() {
$(this ).find(".butt-view").hide();
});
}
</script>
<script>
function PhoneListCtrl($scope) {
$scope.phones = $http.get(url);
}
</script>
<style>
ul{list-style-type:none;}
ul li{background-color:#e1eff2; padding:5px 6px;}
ul li:hover{background-color:#fff;}
.butt-view{background-color:#feb801; border-radius:4px; color:#fff; font: bold 12px Arial, Helvetica, Sans-serif; padding:5px 7px; margin-top:3px; width:40px }
</style>
</head>
<body ng-controller="PhoneListCtrl">
<div id="orders">
<ul>
<li ng-repeat="phone in phones" >
{{phone.name}}
<p>{{phone.snippet}}</p>
<p class="butt-view">View</p>
</li>
</ul>
</div>
</body>
</html>
I'm filling in an array in angularJS using $http.get()
service, by calling a rest api. This array is displayed using ng-repeat
. There is Jquery code to display a button on hovering over each of the <li>
tags. $http
causes a delay in fetching the data, by which time Jquery would have finished binding. So the hover function doesn't work. Any work arounds for this?
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script src="angular.js"></script>
<script src="jquery.js"></script>
<script>
$(document).ready(function() {
myFunction();
});
var myFunction= function(){
$("#orders ul li").hover(
function() {
$(this ).find(".butt-view").show();
},
function() {
$(this ).find(".butt-view").hide();
});
}
</script>
<script>
function PhoneListCtrl($scope) {
$scope.phones = $http.get(url);
}
</script>
<style>
ul{list-style-type:none;}
ul li{background-color:#e1eff2; padding:5px 6px;}
ul li:hover{background-color:#fff;}
.butt-view{background-color:#feb801; border-radius:4px; color:#fff; font: bold 12px Arial, Helvetica, Sans-serif; padding:5px 7px; margin-top:3px; width:40px }
</style>
</head>
<body ng-controller="PhoneListCtrl">
<div id="orders">
<ul>
<li ng-repeat="phone in phones" >
{{phone.name}}
<p>{{phone.snippet}}</p>
<p class="butt-view">View</p>
</li>
</ul>
</div>
</body>
</html>
Share
Improve this question
edited Dec 7, 2013 at 19:38
Nelson Benítez León
50.6k8 gold badges69 silver badges84 bronze badges
asked Nov 24, 2012 at 17:45
Chai NadigChai Nadig
4171 gold badge7 silver badges23 bronze badges
3 Answers
Reset to default 17While the jQuery approach might work OK this is not really an AngularJS-way of solving the problem.
AngularJS promotes UI expressed in declarative way (in other words we do describe a desired effect instead of indicating each and every little step to take in order to achieve the effect). Using directives we can tell AngularJS how we want our UI to look like in response to model mutations. So, with AngularJS we more focus on declaratively describing UI in a template and then driving this UI by model mutations. AngularJS will do the rest of heavy -lifting.
This all might sound a bit cryptic so here is the problem solved the AngularJS way (the model doesn't change, only template does):
<ul>
<li ng-repeat="phone in phones" ng-mouseenter="showView=true" ng-mouseleave="showView=false">
{{phone.name}}
<p>{{phone.snippet}}</p>
<p class="butt-view" ng-show="showView">View</p>
</li>
</ul>
Please note that this is all what is needed to make it work: no need to ad ids to the DOM elements and no need to write any JavaScript code. It allows us to remove 14 lines of JavaScript code and remove dependency on jQuery altogether. Sweet, isn't it?
Finally here is a working jsFiddle: http://jsfiddle.net/GBwLN/4/
Use event delegation, which is better approach introduced by the new .on()
jQuery method, to do it just replace your following code:
$("#orders ul li").hover(
function() {
$(this ).find(".butt-view").show();
},
function() {
$(this ).find(".butt-view").hide();
});
for this one:
$("#orders").on('mouseenter mouseleave', 'li', function(event) {
if (event.type == 'mouseenter') {
$(this ).find(".butt-view").show();
} else {
$(this ).find(".butt-view").hide();
}
});
This way you will attach your event handler to your #orders
div, instead of the individual li
elements, when a li
element is hovered the event will bubble up till gets to your handler on #orders
. This approach is more eficient and will work for dinamycally added new li's.
By the way I'm using mouseenter mouseleave
events which are equivalent to hover
and are more readable in my opinion.
You should use event delegation, however you could also achieve this using a directive:
HTML:
<li ng-repeat="phone in phones" awesome-item>
{{phone.name}}
<p>{{phone.snippet}}</p>
<p class="butt-view">View</p>
</li>
Directive:
angular.module('darthvader', [])
.directive('awesomeItem', function() {
return function($scope, element, attrs) {
element.hover(function() {
$(this).find(".butt-view").show();
},
function() {
$(this).find(".butt-view").hide();
});
};
});