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

javascript - rebinding jquery after angular js ng-repeat - Stack Overflow

programmeradmin3浏览0评论

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
Add a comment  | 

3 Answers 3

Reset to default 17

While 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();
        });
    };
  });
发布评论

评论列表(0)

  1. 暂无评论