切换一个指令会影响ngrepeat内部的其他内容

时间:2016-08-03 03:32:02

标签: angularjs angularjs-directive

我写了一个angularjs指令来显示和隐藏ajax微调器。微调器的可见性由show和hide按钮切换,其功能写在MainController中。控制器内部有一个变量,根据按钮单击设置为true和false。使用isolate范围将此变量传递给指令。当我尝试切换一个微调器时,所有其他微调器也都可见。如何将代码更改为仅切换特定的微调器。

https://plnkr.co/edit/AFmBVbHaBPk66T7UjPC5?p=preview

// Code goes here
angular.module('app',[])
  .controller('MainController',[MainController])
  .directive('loadingDirective',[loadingDirective]);
  function MainController(){
    var mc = this;
    mc.showMe = showMe;
    mc.hideMe = hideMe;
    mc.loading = false;
    function showMe(){
      mc.loading = true;
    }
    function hideMe(){
      mc.loading = false;
    }
  }
  function loadingDirective() {
      return {
        restrict: 'E',
        replace:true,
        scope:{
          loading:"=loading"
        },
        template: '<span class="spinner">Loading…</span>',
        link: function (scope, element, attr) {
              scope.$watch('loading', function (val) {
                
                  if (val)
                      $(element).show();
                  else
                      $(element).hide();
              });
        }
      };
  }
/* Styles go here */

.spinner {
  position: relative;
  /* [1] */
  display: inline-block;
  width: 1em;
  /* [2] */
  height: 1em;
  /* [2] */
  font-size: 32px;
  /* [3] */
  border-bottom: 1px solid;
  /* [4] */
  vertical-align: middle;
  overflow: hidden;
  /* [5] */
  text-indent: 100%;
  /* [5] */
  -webkit-animation: 0.5s spinner linear infinite;
  animation: 0.5s spinner linear infinite;
  /**
   * 1. Make the spinner a circle.
   */
  /**
   * The (optically) non-spinning part of the spinner.
   *
   * 1. Border around entire element fills in the rest of the ring.
   * 2. Paler than the part that appears to spin.
   */
}
.spinner, .spinner:after {
  border-radius: 100%;
  /* [1] */
}
.spinner:after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  border: 1px solid;
  /* [1] */
  opacity: 0.5;
  /* [2] */
}

/**
 * Size variants (built by adjusting `font-size`).
 */
.spinner--small {
  font-size: 16px;
}

.spinner--large {
  font-size: 64px;
}

/**
 * Color overrides.
 */
.spinner--light {
  color: #fff;
}

.spinner--dark {
  color: #333;
}

@-webkit-keyframes spinner {
  to {
    -webkit-transform: rotate(360deg);
  }
}
@keyframes spinner {
  to {
    -webkit-transform: rotate(360deg);
            transform: rotate(360deg);
  }
}
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <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>
  </head>

  <body>
    <h1>Hello Plunker!</h1>
    <div ng-controller="MainController as mc">
      <div ng-repeat="i in [1,2,3,4,5]">
        <loading-directive loading="mc.loading"></loading-directive>
        <button ng-click="mc.showMe()">show</button>
        <button ng-click="mc.hideMe()">hide</button>
      </div>
    </div>
  </body>

</html>

4 个答案:

答案 0 :(得分:2)

如果您希望微调器具有自己的状态,那么它们应该由不同的变量控制。

在您的示例中,可以通过使用数组来保存变量

来实现
<div ng-repeat="i in [1,2,3,4,5]">
    <loading-directive loading="mc.loading[i]"></loading-directive>
    <button ng-click="mc.show(i)">show</button>
    <button ng-click="mc.hide(i)">hide</button>
</div>

mc.loading = {};
function show(i){
  mc.loading[i] = true;
}
function hide(i){
  mc.loading[i] = false;
}

在一个更实际的例子中,如果你有一些数据并且对它们使用ng-repeat,你应该在元素本身内分配加载状态。

这是为ng-repeat

中的每个项目分配状态的常用技巧
mc.fruits = [
    {name:"apple"},
    {name:"orange"},
    {name:"starfruit"}
]

function load(fruit) { fruit.loading = true; }
function noLoad(fruit) { fruit.loading = false; }

<div ng-repeat="fruit in mc.fruits">
    <loading-directive loading="fruit.loading"></loading-directive>
    {{fruit.name}}
    <button ng-click="mc.load(fruit)">show</button>
    <button ng-click="mc.noLoad(fruit)">hide</button>
</div>

答案 1 :(得分:1)

所监视的loading变量对于所使用的所有指令都是通用的,因此当模型更改时,监视条件在您的情况下运行5次,删除所有旋转器。

我使用index查看隐藏或显示的内容,

更新了小提琴:https://plnkr.co/edit/Jjfk6v7TJZHlQicM45ln?p=preview

HTML

<div ng-repeat="i in [1,2,3,4,5]">
    <loading-directive data-index="{{$index}}" loading="mc.loading" offset="mc.offset"></loading-directive>
    <button ng-click="mc.showMe($index)">show</button>
    <button ng-click="mc.hideMe($index)">hide</button>
  </div>

angular.module('app',[])
.controller('MainController',[MainController])
.directive('loadingDirective',[loadingDirective]);
function MainController(){
var mc = this;
mc.showMe = showMe;
mc.hideMe = hideMe;
mc.loading = false;
mc.offset =-1;
function showMe(offset){
  mc.loading = true;
  mc.offset = offset;
}
function hideMe(offset){
  mc.loading = false;
  mc.offset = offset;
  console.log(offset);
}
}
function loadingDirective() {
  return {
    restrict: 'E',
    replace:true,
    scope:{
      loading:"=loading",
      offset:"=offset"
    },
    template: '<span class="spinner">Loading…</span>',
    link: function (scope, element, attr) {


          scope.$watch('[loading, offset]'  , function (val) {

            if(attr.index == scope.offset || scope.offset == -1){
              if (val[0])
                  element.show();
              else
                  element.hide();
            }
          });
    }
  };
}

答案 2 :(得分:1)

 SCRIPT:

  function showMe(i){
  mc.loading = true;
  i=true;
  }

在HTML中添加

  <div ng-repeat="i in [1,2,3,4,5]">
 <span><loading-directive loading="mc.loading" ng-show="i==true"></loading-directive>
    <button ng-click="mc.showMe(i)">show</button></span>
    <button ng-click="mc.hideMe()">hide</button>
  </div>

答案 3 :(得分:1)

工作Plunkr: https://plnkr.co/edit/peGDxYJzKJgiHuPp4zmQ

您需要正确定义指令中的隔离范围。实质上,您的指令仍然依赖于控制器,因为您使用相同的变量$scope.loading来确定所有指令实例的状态。

通过移动确定性变量<div ng-controller="MainController as mc"> <div ng-repeat="i in [1,2,3,4,5]"> <loading-directive></loading-directive> </div> </div> 以及指令内的按钮,我们完全隔离每个指令实例并使它们完全独立。

<强> HTML:

angular.module('app',[])
  .controller('MainController',[MainController])
  .directive('loadingDirective',[loadingDirective]);
  function MainController(){
  }
  function loadingDirective() {
      return {
        restrict: 'E',
        replace:true,
        scope:{},
        template: '<div><span ng-if="loading" class="spinner">Loading…</span>' 
        + '<button ng-click="showMe()">show</button>' 
        + '<button ng-click="hideMe()">hide</button></div>',
        controller: function($scope) {
              $scope.showMe = showMe;
              $scope.hideMe = hideMe;
              function showMe(){
                $scope.loading = true;
              }
              function hideMe(){
                $scope.loading = false;
              }
        }
      };
  }

<强> JS:

given_line = f.readlines()