【问题标题】:Share data between directive scope and controller $scope?在指令范围和控制器 $scope 之间共享数据?
【发布时间】:2015-12-31 05:55:06
【问题描述】:

在这里,我为日期选择器创建了一些示例,它工作正常,但我需要动态设置最小和最大日期。所以我传递了开始和结束日期 像这样的 HTML my-datepicker min="2013-07-23" max="2015-07-23" 在指令范围内我得到了值,我需要在控制器中设置这个值 $scope.datepickerOptions = { startDate :min, endDate:max} 类似这样的东西..

var app = angular.module('myapp', ['ng-bootstrap-datepicker'])

app.directive('myDatepicker', function() {
  return {
    restrict: 'E',
    template: '<input type="text" ng-datepicker ng-options="datepickerOptions"   ng-model="ngModel">',
    scope: {
      date: '=',
      ngModel: '=',
      min: '=',
      max: '=',
    },
    controller: function($scope) {
      $scope.datepickerOptions = {
        format: 'yyyy-mm-dd',
        autoclose: true,
        weekStart: 0,
        startDate :'2013-07-23',
        endDate:'2015-07-23'
      };
    }
  };
})

app.controller('AppCtrl', ['$scope', function ($scope) {
  $scope.date = '2013-08-12'
}]);

var appboot = angular.bootstrap(document, ['myapp']);
<link href="https://rawgit.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.css" rel="stylesheet"/>
<link href="http://netdna.bootstrapcdn.com/bootstrap/2.0.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://code.jquery.com/jquery-2.0.2.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/2.0.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="https://rawgithub.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.js" charset="utf-8"></script>

<body>
<div>
     <div ng-app="myapp" ng-controller="AppCtrl">
      <my-datepicker ng-model ="date"  min="2013-07-23"   max="2015-07-23"></my-datepicker>
     <input id="datepickerMirror" type="text"  data-ng-model="date">
</div>
</div>
</body>

【问题讨论】:

  • $scope.min$scope.max 没用??
  • 我不推荐ng-bootstrap-datepicker。它使用引导 jQuery 插件,并且没有与 ng-model 控制器正确集成。请改用uib-bootstrap-datepickerangular-ui.github.io/bootstrap/#/datepicker 此外,它还实现了min-datemax-date 的属性。
  • 不,我需要使用 ng-bootstrap-datepicker

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

指令控制器中的$scope IS 与指令隔离的范围。您可以从 $scope.min 和 $scope.max 中获取值。

更新您的代码无法执行此操作的原因是因为您使用了“=”绑定,这会导致指令查找名为 @987654322 的变量@在你的范围内。您要么需要将值放入变量中,要么将绑定更改为“@”并使用插值(大括号 {{value}}),或者将日期值用双引号内的单引号括起来,如 min="'2013-07-23'" max="'2015-07-23'" .

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

var app = angular.module('myapp', ['ng-bootstrap-datepicker'])

app.directive('myDatepicker', function() {
  return {
    restrict: 'E',
    template: '<input type="text" ng-datepicker ng-options="datepickerOptions" ng-model="ngModel">',
    scope: {
      dateval: '=',
      ngModel: '=',
      min: '=',
      max: '=',
    },
    controller: function($scope) {
      $scope.datepickerOptions = {
        format: 'yyyy-mm-dd',
        autoclose: true,
        weekStart: 0,
        startDate : $scope.min,
        endDate: $scope.max
      };
    }
  };
})

app.controller('AppCtrl', ['$scope', function ($scope) {
  $scope.dateval = '2013-08-12';
  $scope.min = '2013-07-23';
  $scope.max = '2015-07-23';
}]);

var appboot = angular.bootstrap(document, ['myapp']);

html

<!DOCTYPE html>
<html>

  <head>
<link href="//rawgit.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.css" rel="stylesheet"/>
<link href="//netdna.bootstrapcdn.com/bootstrap/2.0.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//code.jquery.com/jquery-2.0.2.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/2.0.4/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="//rawgithub.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.js" charset="utf-8"></script>

    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>

  </head>


<body>

<div>
     <div ng-app="myapp" ng-controller="AppCtrl">
      <my-datepicker ng-model="dateval"  min="min" max="max"></my-datepicker>
     <input id="datepickerMirror" type="text"  data-ng-model="dateval">
</div>
</div>


</body>

</html>

【讨论】:

  • 在单一形式中,我将放置多个日期选择器。所以我会为两者使用相同的范围..这是不正确的方式...
  • 如果我理解正确,如果您希望在同一页面上有多个不同范围的指令,那么您只需在每个指令上指定不同的最小值和最大值。这些值是来自控制器还是直接在指令上指定值取决于您。但是,如果您确实将其放在指令上,则需要将绑定更改为使用“@”而不是“=”,或者需要在双引号内用单引号将日期值括起来,如min="'2013-07-23'" max="'2015-07-23'"
  • 好的,现在应该可以使用单引号了。你试过了吗?
  • 如果可以的话,能不能把上面的修改一下?
【解决方案2】:

如上一个答案的更新 cmets 中所述,它无法在 UPDATE 上运行的原因是您将“绑定”(范围参数与“=”)到字符串文字。当您尝试设置该变量时,您可能还会遇到控制台错误,类似于对象“未分配”的内容。

话虽如此,您的指令需要一个孤立的范围是否有原因?如果您只是使用“范围:true”设置指令,那么您的指令将原型继承自父范围。这会降低便携性,但目前看来您并没有真正为此而努力。

要设置有用的原型继承,您还需要在 HTML 视图文件中使用 ng-controller 的“as”语法。举个例子,假设:

ng-controller="AppCtrl as appCtl"

然后将 datepickerOptions 的初始化从您的指令移到您的主 AppCtrl 控制器中。就我个人而言,我更喜欢“点”语法,而不是用难以跟踪的变量乱扔范围,因此将其分配给您的控制器而不是范围:

this.datepickerOptions = { /* min, max, etc */ }

现在在您的指令中(使用 scope:true),您可以通过指令 $scope 访问该控制器。所以在你的指令的控制器函数中:

$scope.datepickerOptions = $scope.appCtl.datepickerOptions

请注意,我在这里选择了“点”语法,因为否则原型继承会在您的指令中为 datepickerOptions 创建一个新的范围元素,而不是向上遍历并检查范围链。通过使用点语法,访问之前的作用域变量(appCtl),然后子对象查找(datepickerOptions)使应用程序向上遍历作用域链并获取对象,而不是隐藏它。

最后要解决的是 ngModel。如果您一直在关注,您所要做的就是将 ng-model(在您的指令模板中)设置为读取“appCtl.modelName”,其中 modelName 是您要使用的变量。现在您的控制器将直接分配给它的变量。如果您想在该值更改时执行某些操作,请将其添加到您的 AppCtrl 控制器:

// create a variable so that it can be used in callbacks where "this" changes
var _this = this;

// Create this by hand since its ng-model binding is added dynamically by the directive template
_this.modelName = null;

$scope.$watch(function() { return _this.modelName; }, function(val, oldVal)
{
   // do something here, remembering that _this contains a reference to the controller itself
});

还请注意,在这样做时,您可以摆脱其他输入(datepickermirror),因为您的所有数据都已经在您的控制器中,并且只需通过指令访问。

希望有帮助!

【讨论】:

  • 在我们的聊天中,OP 提到需要在同一页面上有多个具有不同最小值/最大值的日期选择器。这就是需要隔离作用域的原因。
  • 哦,我完全错过了!那么在这种情况下,他只需要为这些值使用变量(如果他想响应更改)并在隔离范围内摆脱 ngModel。没有必要这样做,因为您将模板的 Input 元素的 ng-model 绑定到双向范围变量。然后当输入发生变化时,ng-model 会自动触发对隔离作用域 var 的更新,并且可以在主机控制器中对其进行监视。或者,还有 $rootScope.$on 和 $rootScope.$emit 可以实现类似的响应值变化的结果。 HTH!
猜你喜欢
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
相关资源
最近更新 更多