2013-03-25 153 views
8

我已經創建了一個指令來包裝一個jQuery插件,並且我將一個用於插件的配置對象從控制器傳遞給指令。 (作品)在AngularJS中控制器和指令之間的共享範圍

在配置對象是我想調用一個事件的回調。 (作品)

在回調中,我想修改控制器的$ scope的一個屬性,其中不起作用。 Angular沒有意識到由於某種原因該屬性發生了變化,這導致我相信回調中的$範圍與控制器的$範圍不同。我的問題是我不知道爲什麼。

任何人都可以指向正確的方向嗎?


Click here for Fiddle


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> 

回答

11

有在您的演示工作若干問題的範圍。首先,在dateChange回調中,即使函數本身在控制器內聲明,回調內的this的上下文仍是引導元素,因爲它位於引導句柄內。

每當您從第三方代碼中更改角度範圍值時,角度需要使用$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')。在指令中使用的是多餘的,其中element已經是link回調中的參數之一,並且是實例特定的。與element

+0

一個多想更換dateInput ...有幾個角/引導是超級容易在GitHub上使用 – charlietfl 2013-03-25 02:23:58

+0

感謝設置我直UI指令項目。我立即用$ apply(我可以擁抱你)爲它工作,但我想要做到這一點,所以我試圖實現你展示的方法。我沒有顯示,但應該在我的演示中,我實際上使用* *標記來觸發日期選擇器。所選日期保存在'element.data('datepicker')。getDate()'中。我是AngularJS的新手,所以請原諒我,如果我錯了,但ng模型是爲表單元素。什麼是合適的替代品? – simshaun 2013-03-25 03:32:06

+0

不像我使用jQuery Ui那樣熟悉bootstrap datepicker。然而,不要在輸入中使用'ng-model',可以硬編碼變量以在控制器範圍內更新,或者使用任何想要存儲變量名稱的自定義屬性(例如,如果在頁面的多個位置使用此屬性)。遇到更多問題,請使用''標籤實施創建更新版本。作爲elemnt數據的價值來源很容易在指令中的'scope。$ apply'調用中修改。保持相同的'$ watch' methodlogy。 – charlietfl 2013-03-25 03:38:24

2

綁定到輸入的changeDate事件似乎設置爲在Angular框架之外觸發。要顯示該段落,請在將dateChanged設置爲true後,致電$scope.$apply()。要在延遲之後隱藏段落,可以在傳遞給setTimeout的函數中再次使用$apply(),但是您可能會使用Angular的$timeout()代替避免進一步的麻煩。

Fiddle

相關問題