Angular指令数据绑定无法正常工作

Bja*_*rki 2 html javascript angularjs angularjs-directive

我一直在尝试为我的角度应用程序编写一个共享指令,将输入字段转换为jquery timepicker.

我有两个输入字段,fromTime和toTime,我想在更改fromTime时更新toTime.

我的代码如下:

HTML

<input type="text"
       time-picker="{ timeFormat: 'H:i'}"
       class="input-block-level"
       name="fromTime"
       ng-model="filter.fromTime"
       ng-change="update()" 
/>

<input type="text"
       time-picker="{ timeFormat: 'H:i'}"
       class="input-block-level"
       name="toTime"
       ng-model="filter.toTime"
       ng-change="update()" 
/>
Run Code Online (Sandbox Code Playgroud)

指示

sharedServices.directive('TimePicker', function () {
return {
    restrict: 'A',
    scope: {
        time: "=ngModel"
    },
    link: function(scope, element, attrs) {
                    //Initialize the timepicker
        $(element).timepicker(scope.$eval(attrs.TimePicker));
                    //watch for changes
        scope.$watch('time', function(stuff) {
            console.log('some change', stuff);
        });
    }
};
});
Run Code Online (Sandbox Code Playgroud)

包括sharedServices

var roomsApp = angular.module("roomsApp", ["ngResource",'ui', 'sharedServices','ui.bootstrap']).config(function($routeProvider) { ...
Run Code Online (Sandbox Code Playgroud)

指令加载和timepicker初始化并附加到元素,但是当我更改输入字段时没有任何反应,甚至连元素附加的ng-change事件也没有.页面加载时输入字段也为空,即使模型设置为在应用程序的控制器中包含某些值.谁能解释一下这个问题呢?

*更新 http://plnkr.co/edit/t3BzShezEdh29ZAlI8ZI?p=preview这证明了我的问题.更改日期时,没有任何控制台记录

Mar*_*tin 6

解决问题

您需要监听输入字段的更改并进行更新scope.time.

我做的第一个更改是 jQuery 之后包含Angular ,这样element参数将是一个jQuery对象.

然后听取更改事件并更新scope.time.包含调用scope.$apply以告诉Angular某些内容已发生变化.

element.on('change', function () {
    scope.$apply(function () {
        scope.time = element.datepicker('getDate');
    });
});
Run Code Online (Sandbox Code Playgroud)

Plunker

替代方法

个人在编写应用于输入元素的指令时,我希望允许用户使用ngModel指令来保持数据同步,因为这是一个已知的约定.通过使用ngModel,您还可以(可选)使用它的控制器来添加自定义验证或其他逻辑,例如解析器/格式化程序(在这种情况下不需要).

通过使用该$parse服务,我们可以将数据读/写回ngModel字段.

我也进行了更改,以便在需要时传递datetime选项.

最后,我将第一次datetime()调用移动到编译函数,因为那是应该进行DOM操作的地方.

.directive("datetime", ['$parse', function($parse) {
  return {
      require: '?ngModel',
      restrict: 'A',
      compile: function (element, attrs) {
        var options = $parse(attrs.datetime)() || {};
        console.log('Passed options:', options);

        element.datepicker(options);

        // Return the link function
        return function (scope, element, attrs, ngModel) {
          var getter, setter;

          // If the ngModel directive is used, then set the initial value and keep it in sync
          if (ngModel) {
            getter = $parse(attrs.ngModel);
            setter = getter.assign;

            console.log('ngModel directive used, setting initial value')
            element.datepicker("setDate", getter(scope));

            scope.$watch(attrs.ngModel, function(val, prev) {
              console.log('ngModel changed from', prev, 'to', val);
            });

            element.on('change', function () {
              console.log('change');
              var newValue = element.datepicker('getDate');
              scope.$apply(function () {
                setter(scope, newValue);
              });
            });
          }
        };
      }
  };
}])
Run Code Online (Sandbox Code Playgroud)

该指令使用如下:

<input type="text" datetime="{showButtonPanel: true}" ng-model="parentTime" />
Run Code Online (Sandbox Code Playgroud)

Plunker