8

jQueryプラグインをラップするディレクティブを作成し、プラグインの構成オブジェクトをコントローラーからディレクティブに渡します。(作品)

構成オブジェクトには、イベントで呼び出したいコールバックがあります。(作品)

コールバックで、コントローラーの$scopeのプロパティを変更したいのですが機能しません。Angularは、何らかの理由でプロパティが変更されたことを認識しません。そのため、コールバックの$scopeはコントローラーの$scopeとは異なると思います。私の問題は、理由がわからないことです。

誰かが私を正しい方向に向けることができますか?


フィドルはこちら


app.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内のコンテキストはブートストラップハンドラー内にあるため、ブートストラップ要素です。

サードパーティのコード内からAngularスコープの値を変更する場合は常に、Angularはを使用してそれを知る必要があります$apply。一般に、すべてのサードパーティスコープをディレクティブ内に保持するのが最善です。

より角度のあるアプローチはng-model、入力で使用することです。次に$.watch、モデルの変更に使用します。これにより、コントローラー内のすべてのコードを角度のあるコンテキスト内に保つことができます。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')ページ内の複数の要素でこのディレクティブを使用する場合は、変更する必要があるもう1つの項目を削除します。elementはすでにコールバックの引数の1つであり、linkインスタンス固有であるディレクティブで使用されているのは冗長です。に置き換えdateInputますelement

于 2013-03-25T01:41:48.250 に答える
2

入力にバインドされたchangeDateイベントは、Angularフレームワークの外部で発生するように設定されているようです。段落を表示するには、true$scope.$apply()に設定してから呼び出します。dateChanged遅延後に段落を非表示にするには、に$apply()渡された関数内で再度使用できますが、代わりにsetTimeoutAngularを使用してさらに問題が発生しないようにする可能性があります。$timeout()

フィドル

于 2013-03-25T00:59:43.570 に答える