2016-04-29 34 views
5

Bugün AngularJS'de $ watch kullanarak gerçekten garip davranışlarla karşılaşıyorum.

https://jsfiddle.net/yLeLuard/

Bu örnek bir state değişkenin takip edecek bir hizmet içerir: Aşağıdaki örnek için kodumu basitleştirilmiş. Yönergeler, hizmet aracılığıyla state değişkenini değiştirerek DOM'a bir tıklama olayını bağlamak için kullanılır.

bu örnekte iki sorun vardır:

  1. birinci kapatma düğmesi (üzerine ng tıklama özelliğiyle) sadece Ng- olmadan ikinci tıklamada
  2. iki düğme durumunu değiştirir tıklama tüm

main.html

<div ng-controller="main"> 
    State: {{ api.isOpen | json }} 
    <div ng-click="" open> 
    <button>Open - Working fine</button> 
    </div> 
    <div ng-click="" close> 
    <button>Close - Works, but only on second click</button> 
    </div> 
    <div open> 
    <button>Open - Not Working</button> 
    </div> 
    <div close> 
    <button>Close - Not Working</button> 
    </div> 
</div> 
de devlet değiştirmiyoruz

main.js Eğer click üzerinde yerli olay dinleyicisi kullanarak çünkü var

var myApp = angular.module('myApp', []); 

myApp.controller('main', ['$scope', 'state', function($scope, state) { 
    $scope.api = state; 

    $scope.api.isOpen = false; 

    $scope.$watch('api.isOpen', function() { 
    console.log('state has changed'); 
    }); 
}]); 

myApp.directive('open', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    replace: true, 
    template: '<button>Open</button>', 
    link: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = true; 
     }); 
    } 
    }; 
}]); 


myApp.directive('close', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    replace: true, 
    template: '<button>Close</button>', 
    link: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = false; 
     }); 
    } 
    }; 
}]); 

myApp.service('state', function() { 
    return { 
    isOpen: null 
    }; 
}); 
+2

Yönergelerinizi açıp kapatabilir ve bunun yerine 'ng-click =" api.isOpen = true "' ve 'ng-click =" api.isOpen = false "' işlevlerini kullanabilirsiniz. Bir 'click' olayı – floribon

+0

@floribon'u bağlamak yerine yerel yönergelerin kullanılması daha iyidir, gerçek yönergelerimde çok daha fazla işlevsellik vardır, bu yüzden ng tıklama kullanamıyorum. Bunun yanı sıra, bunun neden düzgün çalışmadığını bilmek istiyorum. – Pascal

+0

Anladım. Daha sonra 'ng-click' 'i kaldırın ve sadece direktifinizi saklayın. Olan şey ng-click'in bir sindirim sistemini tetiklemesiydi, bu yüzden çalışmak gibi görünüyordu ama güvenilmezdi – floribon

cevap

4

. Bu olay, senkronize olmayan ve Açısal özet döngüsünün dışında, bu nedenle kapsamı elle sindirmeniz gerekir.

myApp.directive('open', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    link: function(scope, element) { 
     element.on('click', function() { 
     scope.$apply(function() { 
      state.isOpen = true; 
     }); 
     }); 
    } 
    }; 
}]); 

Sabit keman: https://jsfiddle.net/7h95ct1y/

ı devleti doğrudan değişen öneririm

ng tıklama: ng-click="api.isOpen = true"

+0

Bu doğru cevap gibi görünüyor! Çok teşekkürler. İşte benim sorunumun çözümü için çalıştığım bir örnek: https://jsfiddle.net/yLeLuard/2/ – Pascal

0

öncesi bir bağlantı fonksiyonu olarak bağlantı işlevini koymalıyız, bu sorunu çözer ikinci tıklama.

https://jsfiddle.net/2c9pv4xm/ çalışmıyor kısmına gelince

myApp.directive('close', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    link:{ 
    pre: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = false; 
     console.log('click', state); 
     }); 
    } 
    } 
    }; 
}]); 

, size div tıkladığınızda yüzden ancak butonuna çalışır div üzerinde yönergesini koyuyorlar. Açık yönergeleriniz düğme üzerinde olmalıdır.

Düzenleme: diğer yorumcular durumu doğrudan tıklama düğmesinde değiştirmenizi önerdi. Bunu tavsiye etmem, bu durumda işe yarayabilir, ancak yapılacak bir atamadan daha fazlasına sahip olmak zorundaysanız, bu uygun değildir.

+0

Bunu beğendiniz mi? https://jsfiddle.net/2c9pv4xm/1/ Hizmet güncellemesini göremiyorum. – Pascal

+0

Benim hatam. Kodunu çok çabuk okudum.Bağlantıyı ön çalışma olarak koymak, ancak ng-tıklamasının varlığı bir nedenden dolayı zorunlu görünmektedir. Düzenleme: Bununla birlikte, kapsamı kullanma. $ Uygulaması gerçekten önerilmez, yeni bir özet döngüsünü zorlar ve uygulamanız çok sayıda izleyici içeriyorsa tüm sayfanın özetini yavaşlatabilir. Sadece ng tıklama kullanıyorsanız, onu bir fonksiyona koyardım. – Seedy