简体   繁体   English

如何在ng-repeat循环内分配angularjs事件侦听器?

[英]How do I assign an angularjs event listener inside an ng-repeat loop?

I am new to angularjs. 我是angularjs的新手。 I am trying to create a photo gallery where the initial page is a sheet of thumbnail photos from twitter and instagram created with an angularjs ng-repeat loop. 我正在尝试创建一个图片库,其中初始页面是一张用angularjs ng-repeat循环创建的来自twitter和instagram的缩略图照片。 When the user hovers over a image the image fades and a button appears for the user to click. 当用户将鼠标悬停在图像上时,图像会褪色,并出现一个按钮供用户单击。 I have created the hover effect using ng-mouseenter and ng-mouseleave. 我使用ng-mouseenter和ng-mouseleave创建了悬停效果。 But for some reason when I hover the mouse over an image all of the images are affected. 但是由于某种原因,当我将鼠标悬停在图像上时,所有图像都会受到影响。 Only the single image that I hover should be targeted. 仅定位我悬停的单个图片。 I am not sure what I have done wrong. 我不确定我做错了什么。 Please Help! 请帮忙! The code is below. 代码如下。 Also here is a link to the code online: http://www.petermingione.com/my-demo/ 另外,这里是在线代码的链接: http : //www.petermingione.com/my-demo/

<style>
        * {
            box-sizing: border-box;
            font-family: sans-serif;
        }
        h1, 
        h2{
            margin-left:10px;
        }
        .inner{
            display:inline-block;
            vertical-align:top;
            padding:5px;
            position:relative;
        }
        .inner img{
            width:100%;
        }
        .inner .outer-caption{
            color:black;
            width:375px;
            height:125px;
            background-color:#fc7cab;
            display:flex;
        }
        .inner .outer-caption .inner-caption{
            font-size:14px;
            font-family:sans-serif;
            overflow:hidden;
            width:320px;
            height:70px;
            margin:auto;
        }
        .inner .overlay-color{
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            margin:auto;
            background-color: #fff;
            transition: all .5s;    
        }
        .inner .overlay-text{
            border: 2px solid #7e7e7e;
            color:#7e7e7e;
            font-size: 10px;
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            width:70px;
            height:35px;
            line-height:35px;
            margin:auto;
            border-radius:1px;
            text-align: center;
            transition: all .5s;

    </style>

<body>  
    <h1>{{title}}</h1> 
    <h2>{{myMessage}}</h2>
    <div id="outer" class="outer">
        <div class="inner" ng-mouseenter="makeVisibile()" ng-mouseleave="makeInVisibile()" ng-repeat="x in insideData">
            <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
             <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
            <div class="overlay-color" ng-style="overlayColorStyles" ></div>
            <div class="overlay-text" ng-style="overlayTextStyles">VIEW</div>
        </div>
    </div>

<script>

    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.overlayColorStyles = {"opacity": 0};
        $scope.overlayTextStyles =  {"opacity": 0};

        $scope.makeVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = .75;
            //document.getElementById("overlay-text").style.opacity = 1;
            $scope.overlayColorStyles = {"opacity" : .75};
            $scope.overlayTextStyles = {"opacity" : 1};

        }
        $scope.makeInVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = 0;
            //document.getElementById("overlay-text").style.opacity = 0;
            $scope.overlayColorStyles = {"opacity" : 0};
            $scope.overlayTextStyles = {"opacity" : 0};

        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

</script>

Hi, Thanks again for the answer Aaron. 嗨,再次感谢您的回答亚伦。 I have one more issue that I need to resolve. 我还有一个需要解决的问题。 I am now building out the light-box portion of the app. 我现在正在构建该应用的灯箱部分。 That is the overlay that you see when you click on the view button. 那就是您单击查看按钮时看到的覆盖。 I have placed the latest version here online: http://www.petermingione.com/my-demo/ As you can see regardless of which image you click on the only image that appears is the first image in the collection. 我已将最新版本在线放置在这里: http : //www.petermingione.com/my-demo/正如您所看到的,无论单击哪个图像,您单击的唯一出现的图像都是该集合中的第一幅图像。 Again this is another problem with ng-repeat. 同样,这是ng-repeat的另一个问题。 The image is located in each object as mainImage.url and I am accessing it through x.mainImage.url in the ng-repeat loop. 该图像作为mainImage.url位于每个对象中,我正在ng-repeat循环中通过x.mainImage.url访问它。 I am not sure why it isn't working. 我不确定为什么它不起作用。 Any help that anyone can give me would be greatly appreciated. 任何人都能给我的任何帮助将不胜感激。 The code is below and online: 该代码在下面并在线提供:

   <style>
    * {
        box-sizing: border-box;
        font-family: sans-serif;
    }
    h1, 
    h2{
        margin-left:10px;
    }

    .outer-wrapper{
        overflow: hidden;
    }
    .inner-wrapper{
        display:inline-block;
        vertical-align:top;
        padding:5px;
        position:relative;
    }
    .inner-wrapper img{
        width:100%;
    }
    .inner-wrapper .outer-caption{
        color:black;
        width:100%;
        padding-top:35%;
        background-color:#fc7cab;
        position:relative;
    }
    .inner-wrapper .outer-caption .inner-caption{
        font-size:14px;
        font-family:sans-serif;
        overflow:hidden;
        width:75%;
        height:70px;
        position:absolute;
        top:0;
        left:0;
        bottom:0;
        right:0;
        margin:auto;
    }
    .inner-wrapper .item-overlay-color{
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        margin:auto;
        background-color: #fff;
        transition: all .5s;
        opacity: 0.0;   
    }
    .inner-wrapper:hover .item-overlay-color {
        opacity: 0.75;
    }
    .inner-wrapper .item-overlay-text{
        border: 2px solid #7e7e7e;
        color:#7e7e7e;
        font-size: 10px;
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        width:70px;
        height:35px;
        line-height:35px;
        margin:auto;
        border-radius:1px;
        text-align: center;
        transition: all .5s;
        opacity: 0.0;
    }
    .inner-wrapper:hover .item-overlay-text {
        opacity: 1.0;
    }
    .inner-wrapper .page-overlay {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0; 
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(255,255,255,0.75);
        z-index: 2;
        cursor: pointer;
    }
    .inner-wrapper #page-overlay {
        opacity:0;
        transition: all .5s;
        pointer-events:none;
    }
    .inner-wrapper .page-overlay .text{
        position: absolute;
        top: 50%;
        left: 50%;
        font-size: 50px;
        color: white;
        transform: translate(-50%,-50%);
        -ms-transform: translate(-50%,-50%);
    }
    .inner-wrapper .page-overlay .text .close{
        position:absolute;
        top:0;
        right:0;
        color:#000;
        font-weight: lighter;
        font-size: 30px;
        line-height: 30px;
        padding-top:5px;
        padding-right:5px;
    }

    @media screen and (min-width: 1301px){
        .inner-wrapper{
            width:16.6666%;
        }
    }
    @media screen and (max-width: 1300px){
        .inner-wrapper{
            width:20%;
        }
    }
    @media screen and (max-width: 1024px){
        .inner-wrapper{
            width:25%;
        }
    }
    @media screen and (max-width: 768px){
        .inner-wrapper{
            width:50%;
        }
    }
    @media screen and (max-width: 480px){
        .inner-wrapper{
            width:100%;
        }
    }

  </style>

 <body>
<div id="outer-wrapper" class="outer-wrapper">
    <div id="inner-wrapper" class="inner-wrapper" ng-repeat="x in insideData">
        <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
        <div class="outer-caption" ng-if="x.service=='Twitter'&& x.mediaType!='image'">
            <div class="inner-caption">{{x.caption}}</div>
        </div>
        <div class="item-overlay-color"></div>
        <div class="item-overlay-text" ng-click="showOverlay()">VIEW</div>
        <div id="page-overlay" class="page-overlay">
                <div class="text">
                    <img ng-src='{{x.mainImage.url}}'>
                    <span class="close" ng-click="hideOverlay()">X</span>
                </div>
        </div>
    </div>
</div>
 </body>
  <script>
    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.showOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 1;
            document.getElementById("page-overlay").style["pointer-events"] = "auto";
        }
        $scope.hideOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 0;
            document.getElementById("page-overlay").style["pointer-events"] = "none";
        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

I know you asked how to do this the angular way, but ng-mouseenter and ng-mouseleave are VERY performance intensive, if you're planning to use this in a real world app, this should really be done with css. 我知道您问过如何以角度的方式进行此操作,但是ng-mouseenter和ng-mouseleave的性能非常高,如果您打算在现实世界中的应用中使用它,则应该使用CSS来完成。

I'll go ahead and show you how to fix your version, and then I'll give you a css version that's MUCH more efficient :) 我将继续向您展示如何修复您的版本,然后为您提供更高效的CSS版本:)

For this use case, there's a very useful variable $index, which can be referenced in an angular template anywhere within inside of an ng-repeat tag to get the index of the current data item being iterated over. 对于此用例,有一个非常有用的变量$ index,可以在ng-repeat标签内部任何地方的角度模板中引用该变量,以获取要迭代的当前数据项的索引。 You should use that to save the index of the item that is currently hovered to the controller scope. 您应该使用它来保存当前悬停在控制器范围内的项目的索引。 Then, when the mouse leaves the item, you can discard the saved index. 然后,当鼠标离开项目时,您可以放弃保存的索引。

Then when you're assigning styles, you can use a ternary to assign active or inactive styles based on whether the items index matches the active index variable saved on scope. 然后,当您分配样式时,您可以使用三元数来根据项目索引与保存在范围内的活动索引变量相匹配来分配活动或非活动样式。

Also, in case you aren't familiar with the, a ternary expression is a shorthand for a conditional statement of the form conditional_expression ? value_returned_if_true : value_returned_if_false 另外,如果您不熟悉,三元表达式是条件语句的简写形式,形式为conditional_expression ? value_returned_if_true : value_returned_if_false conditional_expression ? value_returned_if_true : value_returned_if_false . conditional_expression ? value_returned_if_true : value_returned_if_false It's good for writing very concise conditional statements in javascript (or, in this case, an angular template with interprets javascript :) ) 这非常适合在javascript中编写非常简洁的条件语句(或在这种情况下,带有解释javascript的角度模板:))

So, for this example, I use a combination of a ternary expression and saving the index of the last item the mouse entered to assign hover or non-hovered styles to each item. 因此,在此示例中,我结合使用了三元表达式并保存了鼠标输入的最后一项的索引,以将鼠标悬停或未悬停的样式分配给每个项目。

And abbreviated version of your example: 和示例的缩写版本:

Angular controller: 角度控制器:

app.controller('exampleController', function($scope) {
  $scope.overlayColorStyles = {"opacity": 0};
  $scope.overlayTextStyles  = {"opacity": 0};
  $scope.overlayTextStylesActive  = {"opacity": 1};
  $scope.overlayColorStylesActive = { "opacity": .75};
  $scope.activeItemIndex    = null;
});

Template: 模板:

<div id="outer" class="outer">
  <div class="inner"
      ng-mouseenter="$scope.activeItemIndex = $index"
      ng-mouseleave="$scope.activeItemIndex = null"
      ng-repeat="x in insideData">
      <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
      <div class="overlay-color"
        ng-style="$scope.activeItemIndex === $index ? overlayColorStylesActive : overlayColorStyles">
      </div>
      <div class="overlay-text"
        ng-style="$scope.activeItemIndex === $index ? overlayTextStylesActive : overlayTextStyles">
        VIEW
      </div>
  </div>
</div>

Again though, this code should only be used for the sake of a learning exercise. 同样,此代码仅应用于学习练习。 Angular's job is not to apply styles based on user interaction, and if you try to use it that way, your application with get super slow as you start to add more items. Angular的工作不是应用基于用户交互的样式,如果您尝试以这种方式使用样式,则当您开始添加更多项时,应用程序将变得非常慢。 Doing this with css is pretty trivial and will result in significantly better performance :) 用css做到这一点非常简单,并且可以显着提高性能:)

css version below: 下面的css版本:

html: HTML:

<div id="outer" class="outer">
  <div class="inner"
      ng-repeat="x in insideData">
      <img ng-if="x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if="x.service=='Twitter'&& x.mediaType!='image'" class="outer-caption"><div class="inner-caption">{{x.caption}}</div></div>
      <div class="overlay-color"></div>
      <div class="overlay-text">VIEW</div>
  </div>
</div>

css CSS

.overlay-color {
  opacity: 0.0;
}

.overlay-text {
  opacity: 0.0;
}

.inner:hover .overlay-text {
  opacity: 1.0;
}

.inner:hover .overlay-color {
  opacity: 0.75;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM