在指令范围和控制器$ scope之间共享数据?

时间:2021-10-26 13:36:39

Here I created some sample for date picker, which is working fine but I need to set min and max date dynamically.. so i am passing the start and end date from Html like this my-datepicker min="2013-07-23" max="2015-07-23" in directive scope i get the value and I need to set this value in controller $scope.datepickerOptions = { startDate :min, endDate:max} some thing like this..

这里我为日期选择器创建了一些示例,它工作正常,但我需要动态设置最小和最大日期..所以我从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>

2 个解决方案

#1


1  

$scope in the directive controller IS the isolated scope from the directive. You can just grab the values from $scope.min and $scope.max.

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

Update The reason your code can't do this is because you're using the '=' binding which causes your directive to look for a variable named 2013-07-23 on your scope. You either need to put your value in a variable, or change the binding to '@' and use interpolation (the curly braces {{value}}), or surround your date value with single quotes inside the double quotes as in min="'2013-07-23'" max="'2015-07-23'".

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

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

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

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>

#2


0  

As mentioned in the previous answer's Updated comments, the reason it's not working on UPDATE is that you're "binding" (scope params with "=") to a string literal. You're likely also getting a console error when you attempt to set that variable, something along the lines of object "non-assign".

正如前面回答的更新注释中所提到的,它不在UPDATE上工作的原因是你将“绑定”(范围参数与“=”)一个字符串文字。当您尝试设置该变量时,您可能也会收到控制台错误,这是对象“非分配”的行。

That being said, is there a reason your directive NEEDS an isolated scope? If you just set the directive up using "scope: true", then your directive will prototypically inherit from the parent scope. This reduces portability, but it doesn't look like you're really shooting for that at this point.

话虽如此,你的指令是否需要一个孤立的范围?如果您只是使用“scope:true”设置指令,那么您的指令将原型继承父作用域。这降低了便携性,但在这一点上看起来并不像你那样。

To setup useful prototypical inheritance you'll need to also use the "as" syntax of ng-controller in your HTML view file. For the sake of example, let's say:

要设置有用的原型继承,您还需要在HTML视图文件中使用ng-controller的“as”语法。为了举例,让我们说:

ng-controller="AppCtrl as appCtl"

Then move the initialization of datepickerOptions from your directive into your main AppCtrl controller. Personally I prefer the "dot" syntax as opposed to littering the scope with variables that are hard to track, so assign it to your controller instead of scope:

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

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

Now in your directive (using scope:true), you can access that controller via the directive $scope. So in your directive's controller function:

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

$scope.datepickerOptions = $scope.appCtl.datepickerOptions

Note that I chose the "dot" syntax here because otherwise the prototypical inheritance would create a new scope element for datepickerOptions in your directive instead of traversing up and checking the scope chain. By using the dot syntax, the previous scope variable (appCtl) is accessed, and then the sub-object lookup (datepickerOptions) causes the app to traverse the scope chain up and get the object instead of shadowing it.

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

The last piece to address is ngModel. If you're following along up to now, all you have to do is set the ng-model (in your directive template) to read "appCtl.modelName" where modelName is the variable you want to use. Now your controller will have that variable assigned directly to it. If you want to do something when that value changes, add this to your AppCtrl controller:

最后要解决的问题是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
});

Also note that in doing this you can get rid of that other input (datepickermirror) since all your data is already in your controller, and simply accessed by the directive.

另请注意,在执行此操作时,您可以删除其他输入(datepickermirror),因为您的所有数据都已存在于控制器中,并且只需通过指令访问。

Hope that helps!

希望有所帮助!

#1


1  

$scope in the directive controller IS the isolated scope from the directive. You can just grab the values from $scope.min and $scope.max.

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

Update The reason your code can't do this is because you're using the '=' binding which causes your directive to look for a variable named 2013-07-23 on your scope. You either need to put your value in a variable, or change the binding to '@' and use interpolation (the curly braces {{value}}), or surround your date value with single quotes inside the double quotes as in min="'2013-07-23'" max="'2015-07-23'".

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

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

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

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>

#2


0  

As mentioned in the previous answer's Updated comments, the reason it's not working on UPDATE is that you're "binding" (scope params with "=") to a string literal. You're likely also getting a console error when you attempt to set that variable, something along the lines of object "non-assign".

正如前面回答的更新注释中所提到的,它不在UPDATE上工作的原因是你将“绑定”(范围参数与“=”)一个字符串文字。当您尝试设置该变量时,您可能也会收到控制台错误,这是对象“非分配”的行。

That being said, is there a reason your directive NEEDS an isolated scope? If you just set the directive up using "scope: true", then your directive will prototypically inherit from the parent scope. This reduces portability, but it doesn't look like you're really shooting for that at this point.

话虽如此,你的指令是否需要一个孤立的范围?如果您只是使用“scope:true”设置指令,那么您的指令将原型继承父作用域。这降低了便携性,但在这一点上看起来并不像你那样。

To setup useful prototypical inheritance you'll need to also use the "as" syntax of ng-controller in your HTML view file. For the sake of example, let's say:

要设置有用的原型继承,您还需要在HTML视图文件中使用ng-controller的“as”语法。为了举例,让我们说:

ng-controller="AppCtrl as appCtl"

Then move the initialization of datepickerOptions from your directive into your main AppCtrl controller. Personally I prefer the "dot" syntax as opposed to littering the scope with variables that are hard to track, so assign it to your controller instead of scope:

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

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

Now in your directive (using scope:true), you can access that controller via the directive $scope. So in your directive's controller function:

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

$scope.datepickerOptions = $scope.appCtl.datepickerOptions

Note that I chose the "dot" syntax here because otherwise the prototypical inheritance would create a new scope element for datepickerOptions in your directive instead of traversing up and checking the scope chain. By using the dot syntax, the previous scope variable (appCtl) is accessed, and then the sub-object lookup (datepickerOptions) causes the app to traverse the scope chain up and get the object instead of shadowing it.

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

The last piece to address is ngModel. If you're following along up to now, all you have to do is set the ng-model (in your directive template) to read "appCtl.modelName" where modelName is the variable you want to use. Now your controller will have that variable assigned directly to it. If you want to do something when that value changes, add this to your AppCtrl controller:

最后要解决的问题是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
});

Also note that in doing this you can get rid of that other input (datepickermirror) since all your data is already in your controller, and simply accessed by the directive.

另请注意,在执行此操作时,您可以删除其他输入(datepickermirror),因为您的所有数据都已存在于控制器中,并且只需通过指令访问。

Hope that helps!

希望有所帮助!