8

我创建了一个指令来包装 jQuery 插件,并将插件的配置对象从控制器传递给指令。(作品)

在配置对象中是一个我想在事件上调用的回调。(作品)

在回调中,我想修改控制器的 $scope 上的一个属性,它不起作用。由于某种原因,Angular 无法识别该属性已更改,这使我相信回调中的 $scope 与控制器的 $scope 不同。我的问题是我不知道为什么。

谁能指出我正确的方向?


单击此处获取小提琴


应用程序.js

var app = angular.module('app', [])
    .directive('datepicker', function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                // Uncommenting the line below causes
                // the "date changed!" text to appear,
                // as I expect it would.
                // scope.dateChanged = true;

                var dateInput = angular.element('.datepicker')

                dateInput.datepicker(scope.datepickerOpts);

                // The datepicker fires a changeDate event
                // when a date is chosen. I want to execute the
                // callback defined in a controller.
                // ---
                // PROBLEM: 
                // Angular does not recognize that $scope.dateChanged
                // is changed in the callback. The view does not update.
                dateInput.bind('changeDate', scope.onDateChange);
            }
        };
    });

var myModule = angular.module('myModule', ['app'])
    .controller('MyCtrl', ['$scope', function ($scope) {
        $scope.dateChanged = false;

        $scope.datepickerOpts = {
            autoclose: true,
            format: 'mm-dd-yyyy'
        };

        $scope.onDateChange = function () {
            alert('onDateChange called!');

            // ------------------
            // PROBLEM AREA:
            // This doesnt cause the "date changed!" text to show.
            // ------------------
            $scope.dateChanged = true;

            setTimeout(function () {
                $scope.dateChanged = false;
            }, 5000);
        };
    }]);

html

<div ng-controller="MyCtrl">
    <p ng-show="dateChanged">date changed!</p>
    <input type="text" value="02-16-2012" class="datepicker" datepicker="">
</div>
4

2 回答 2

11

您的演示中存在许多范围问题。首先,在dateChange回调中,即使函数本身在控制器中声明,this回调中的上下文也是引导元素,因为它在引导处理程序中。

每当您从第三方代码中更改角度范围值时,角度都需要通过使用$apply. 通常最好将所有第三方范围保留在指令内。

更角度的方法是ng-model在输入上使用。然后$.watch用于更改模型。这有助于将控制器内的所有代码保持在角度上下文中。在任何 Angular 应用程序中都很少用于不用于ng-model任何表单控件

 <input type="text"  class="datepicker" datepicker="" ng-model="myDate">

在指令内:

dateInput.bind('changeDate',function(){
      scope.$apply(function(){
         scope[attrs.ngModel] = element.val()
      });
});

然后在控制器中:

$scope.$watch('myDate',function(oldVal,newVal){ 
       if(oldVal !=newVal){
           /* since this code is in angular context will work for the hide/show now*/
            $scope.dateChanged=true;
             $timeout(function(){
                   $scope.dateChanged=false;
              },5000);
        }        
});

演示:http: //jsfiddle.net/qxjck/10/

编辑var dateInput = angular.element('.datepicker')如果您想在页面中的多个元素上使用此指令,则应该更改的另一项是删除。element在回调中已经是参数之一的指令中使用它是多余的link,并且是特定于实例的。替换dateInputelement

于 2013-03-25T01:41:48.250 回答
2

绑定到输入的 changeDate 事件似乎设置为在 Angular 框架之外触发。要显示段落,请$scope.$apply()在设置dateChanged为 true 后调用。要在延迟后隐藏段落,您可以$apply()在传递给的函数中再次使用setTimeout,但使用 Angular 可能会避免进一步的麻烦$timeout()

小提琴

于 2013-03-25T00:59:43.570 回答