【问题标题】:toggling one directive effects other dircetive inside ngrepeat切换一个指令会影响 ngrepeat 中的其他指令
【发布时间】:2016-12-08 14:28:38
【问题描述】:

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

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>

【问题讨论】:

  • Icycool answer 更适合我的问题,因为我需要在 ajax 调用之前和之后控制微调器的切换以表示加载。但是Nivedit 提供的解决方案非常通用,可以在很多情况下使用。非常感谢你们的帮助。

标签: angularjs angularjs-directive


【解决方案1】:

loading 变量watched 对于所有使用的指令都是通用的,因此当模型更改时,监视条件在您的情况下运行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】:
     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】:

      如果你想让微调器有自己的状态,那么它们应该由不同的变量控制。

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

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

      【讨论】:

        【解决方案4】:

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

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

        通过移动确定性变量$scope.loading 以及指令内的按钮,我们完全隔离了每个指令实例并使它们成为完全独立的单元。

        HTML:

        <div ng-controller="MainController as mc">
          <div ng-repeat="i in [1,2,3,4,5]">
            <loading-directive></loading-directive>
          </div>
        </div>
        

        JS:

        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;
                      }
                }
              };
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-01
          • 2017-05-29
          相关资源
          最近更新 更多