簡體   English   中英

Angular指令數據綁定無法正常工作

[英]Angular directive data binding not working properly

我一直在嘗試為我的angular應用程序編寫一個共享指令,該指令將輸入字段轉換為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()" 
/>

指示

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);
        });
    }
};
});

包含sharedServices

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

指令加載並且時間選擇器被初始化並附加到元素,但是當我更改輸入字段時,什么也沒有發生,甚至連到元素的ng-change事件也沒有發生。 頁面加載時,即使模型設置為在應用程序的控制器中包含某些值,輸入字段也為空。 誰能闡明這件事?

* 更新 http://plnkr.co/edit/t3BzShezEdh29ZAlI8ZI?p=preview這可以說明我的問題。 日期更改后,控制台未記錄任何內容

解決問題

您需要收聽對輸入字段的更改並更新scope.time

我所做的第一個更改是 jQuery 之后包含Angular,這樣element參數將是一個jQuery對象。

然后聽一下change事件並更新scope.time 將調用包裝在scope.$apply app中,以告知Angular某些更改。

element.on('change', function () {
    scope.$apply(function () {
        scope.time = element.datepicker('getDate');
    });
});

Plunker

替代方法

就個人而言,在編寫應用於輸入元素的指令時,我希望允許用戶使用ngModel指令來保持數據同步,因為這是已知的約定。 通過使用ngModel,您還可以(可選)使用其控制器來添加自定義驗證或其他邏輯,例如解析器/格式化程序(在這種情況下不需要)。

通過使用$parse服務,我們可以將數據讀/寫回ngModel字段。

我也進行了更改,以便可以根據需要傳遞datetime選項。

最后,我將第一個datetime()調用移至了compile函數,因為這是應該進行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);
              });
            });
          }
        };
      }
  };
}])

指令的用法如下:

<input type="text" datetime="{showButtonPanel: true}" ng-model="parentTime" />

Plunker

更新:這是一個使用jquery datepicker的非常基本的實現-http://plnkr.co/edit/4JZIWo6mJqg59F5o7xdh? p= preview

angular
.module("demo", [])
.directive("test", function() {
  return {
      restrict: 'A',
      scope: {
          time: "="
      },
      link: function(scope, element, attrs) {
        console.log("scope.time:" + scope.time);
        $(element).datepicker();
        $(element).datepicker("setDate", scope.time);
      }
  };
})
.controller("demoCtl", function($scope){
  $scope.parentTime = new Date();
});

看一下angular-ui日歷模塊 如果您不想使用它,可以查看他們的代碼以幫助您。


另外,設置示波器的方式看起來很奇怪。 我認為您想將指令的time屬性綁定到由該指令的父作用域管理的屬性,而不是ng-model。

嘗試這個

return {
    restrict: 'A',
    scope: {
        time: "="
    },
    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);
        });
    }
};

並使用它

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

您也不需要將attrs.TimePicker包裝在$scope.eval

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM