2

入力フィールドをjquery timepickerに変換する角度アプリ用の共有ディレクティブを作成しようとしています。

fromTime と toTime の 2 つの入力フィールドがあり、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);
        });
    }
};
});

含まれる共有サービス

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

ディレクティブが読み込まれ、タイムピッカーが初期化されて要素にアタッチされますが、入力フィールドを変更しても、要素にアタッチされている ng-change イベントでさえ何も起こりません。モデルがアプリのコントローラーで何らかの値を含むように設定されていても、ページが読み込まれると、入力フィールドも空になります。誰かが問題に光を当てることができますか?

*更新 http://plnkr.co/edit/t3BzShezEdh29ZAlI8ZI?p=previewこれは私の問題を示しています。日付が変更された場合、コンソールには何も記録されません

4

2 に答える 2

6

問題を解決するには

入力フィールドへの変更をリッスンして更新する必要がありますscope.time

私が行った最初の変更は、 jQuery のelementに Angular を含めることでした。これにより、パラメーターは jQuery オブジェクトになります。

次に、 change イベントと update をリッスンしscope.timeます。呼び出しをラップしてscope.$apply、何かが変更されたことを Angular に伝えます。

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

Plunker

代替アプローチ

個人的には、入力要素に適用されるディレクティブを作成するときに、ユーザーがngModelディレクティブを使用してデータの同期を維持できるようにしたいと考えています。これは既知の規則であるためです。ngModel を使用することで、(オプションで) コントローラーを使用してカスタム検証やその他のロジック (パーサー/フォーマッターなど) を追加することもできます (この場合は不要です)。

この$parseサービスを使用することで、データを ngModel フィールドに読み書きすることができます。

また、必要に応じて日時オプションを渡せるように変更しました。

最後に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);
              });
            });
          }
        };
      }
  };
}])

そして、ディレクティブは次のように使用されます。

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

Plunker

于 2013-06-06T20:27:02.347 に答える
0

更新: これは、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 calendar module をご覧ください。使用したくない場合は、コードを参照してください。


また、スコープの設定方法が奇妙に見えます。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

于 2013-06-06T14:50:53.953 に答える