1

我在这里要做的是创建一个指令,允许我设置仅适用于我正在呈现的 html 标记内的临时变量。用例是这样的:

<div class="input-group" ng-local="opened = false" ng-blur="opened = false;">
    <input type="text" class="form-control" uib-datepicker-popup="longDate" ng-model="start" is-open="opened" ng-focus="opened = true;" />
    <span class="input-group-btn">
        <button type="button" ng-click="opened = true;" class="fa fa-calendar" ></button>
    </span>
</div>

这里的想法是 ng-local 指令创建一个变量opened并将该变量设置为初始值false。指令中的所有内容都是一个嵌入的模板。这里的好处是我可以在一个页面上拥有多个日期选择器,所有使用相同变量的人opened都无需在控制器的范围内拥有一堆不同的变量,这些变量仅用作内部内容的临时变量分区。但是,由于这将以多种不同的方式使用,我不想为每个用例制定不同的指令。

我在这方面的第一次尝试非常顺利。但是,我遇到了一个问题,start即没有从 datepicker 正确访问父范围变量。我对 $transclude 功能不是很熟悉,所以我希望有人能指出我正确的方向。这是我目前编写的指令:

(function () {
    angular.module('myApp').directive('ngLocal', [function () {
        return {
            restrict: 'A',
            transclude: 'element',
            replace: false,
            scope: {
                ngLocal: '@'
            },
            link: function ngLocalLink(directiveScope, element, attrs, ctrl, $transclude) {
                $transclude(directiveScope, function ngLocalTransclude(clone, scope) {
                    element.empty();
                    element.replaceWith(clone);
                    scope.$eval(directiveScope.ngLocal);
                });
            }
        };
    }]);
})();

提前致谢!

编辑

这是一个plunkr链接

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

4

4 回答 4

0

我希望获得类似于ng-repeat您不必通过嵌入元素中的父范围处理所有内容的功能。

ng-repeat不使用隔离范围。它使用继承的范围。

有关指令范围的更多信息,请参阅AngularJS $compile 服务 API 参考 - 范围


例子

此自定义指令多次嵌入其内容,每次都创建一个新的继承范围。重复次数由读取repeat属性确定。

angular.module('myApp').directive('repeat', function () {
    return{
        scope: false,
        transclude: 'element',
        link : function(scope, element, attrs, ctrl, transcludeFn){
            var parent = element.parent();
            var repeatNum = attrs.repeat;
            for(var i = 1;i<= repeatNum;++i){
                var childScope = scope.$new();
                childScope.$index = i;
                transcludeFn(childScope, function (clone) {
                    parent.append(clone);
                })
            }
        }
    }
})

JSFiddle 上的DEMO

于 2016-01-22T19:52:37.327 回答
0

尝试嵌套指令。外部指令封装了您希望共享的数据,内部指令从外部提供的函数中获取数据。

演示链接: https ://plnkr.co/edit/4n6kf40ZMf7lRCad5ofe?p=preview

编码:

angular.module('myapp', [])
  .directive('outer', function () {
    return {
      restrict: 'E',
      transclude: true,
      scope: {
        value: '='
      },
      template: function(element, attrs) {
        return '<div>outer! value = {{value}}<div ng-transclude></div></div>';
      },
      controller: function($scope) {
        this.getValue = function() {
          return $scope.value;
        }
      }
    }
  })
  .directive('inner', function () {
    return {
      restrict: 'E',
      template: function(element, attrs) {
        return '<div>inner! value = {{value}}</div>';
      },
      require: '^outer',
      link: function (scope, element, attrs, parentCtrl) {
        scope.$watch(
          function() {
            return parentCtrl.getValue();
          }, function(oldValue, newValue) {
            scope.value = parentCtrl.getValue();
          }
        );
      }
    }
  });
于 2016-01-22T19:15:58.220 回答
0

尝试$parent.localDate改用。

<div class="input-group" ng-local="localOpen = false">
      <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen" ng-model="$parent.localDate" />
      <span class="input-group-btn">
          <button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
      </span>
</div>

如果您不想使用 $parent ,则可以使用隔离范围,并设置要使用的变量:

<div class="input-group" ng-local="localOpen = false" date="localDate">
      <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen"  ng-model="date" />
      <span class="input-group-btn">
          <button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
      </span>
</div>

angular.module('myApp').directive('ngLocal', [function () {
return {
    restrict: 'A',
    transclude: 'element',
    replace: false,
    scope: {
        ngLocal: '@',
        date: '='
    },
    link: function ngLocalLink(directiveScope, element, attrs, ctrl, $transclude) {
        $transclude(directiveScope, function ngLocalTransclude(clone, scope) {
            element.empty();
            element.replaceWith(clone);
            scope.$eval(directiveScope.ngLocal);
        });
    }
};
}]);

这是分叉的 plunker:https ://plnkr.co/edit/4zrNzbSc5IwqqbE2ISE1?p=preview

于 2016-01-22T19:02:52.640 回答
0

您不需要在指令中嵌入,只需创建范围或隔离范围

样本

angular.module('myApp', ['ngAnimate', 'ui.bootstrap']);




// CONTROLLER
angular.module('myApp').controller('myController', function($scope) {


  $scope.dates = {
      workingDate : new Date(),
      brokenDate1 : new Date(),
      brokenDate2 : new Date(),
      localDate : new Date(),
  }

});



// DIRECTIVE
angular.module('myApp').directive('ngLocal', [
  function() {
    return {
      restrict: 'A',
      replace: false,
      scope: true //directive have own scope
    };
  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.1.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">

<div ng-app="myApp">

  <div ng-controller="myController">


    <h4>This one works</h4>
    <div class="input-group">
      <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="workingOpen" ng-model="dates.workingDate" />
      <span class="input-group-btn">
        <button class="btn btn-secondary" type="button" ng-click="workingOpen = true" >OPEN</button>
      </span>
    </div>

    <br/>
    <br/>
    <br/>



    <h4>This is the problem I'm trying to solve</h4>
    <h4>Both datepickers use "brokenOpen" so they both open whenever either is clicked</h4>
    <div style="width: 40%; display: inline-block;" ng-local>
      <div class="input-group">
        <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="brokenOpen" ng-model="dates.brokenDate1" />
        <span class="input-group-btn">
          <button class="btn btn-secondary" type="button" ng-click="brokenOpen = true" >OPEN</button>
        </span>
      </div>
    </div>
    <div style="width: 40%;  display: inline-block;" ng-local>
      <div class="input-group">
        <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="brokenOpen" ng-model="dates.brokenDate2" />
        <span class="input-group-btn">
          <button class="btn btn-secondary" type="button" ng-click="brokenOpen = true" >OPEN</button>
        </span>
      </div>
    </div>



    <br/>
    <br/>
    <br/>

    <h4>This is using my directive</h4>
    <h4>The date does not update correctly to the parent scope</h4>

    <div class="input-group" ng-local="localOpen = false">
      <input type="text" class="form-control" uib-datepicker-popup="longDate" is-open="localOpen" ng-model="dates.localDate" />
      <span class="input-group-btn">
              <button class="btn btn-secondary" type="button" ng-click="localOpen = true;" >OPEN</button>
          </span>
    </div>

    <label>See how the date is not updating: {{dates.localDate}}</label>


  </div>
</div>

于 2016-01-22T19:06:42.580 回答