एंगुलरज: 'सिंटैक्स के रूप में कंट्रोलर' और $ वॉच


153

controller asसिंटैक्स का उपयोग करते समय संपत्ति परिवर्तन पर कैसे सदस्यता लें ?

controller('TestCtrl', function ($scope) {
  this.name = 'Max';
  this.changeName = function () {
    this.name = new Date();
  }
  // not working       
  $scope.$watch("name",function(value){
    console.log(value)
  });
});
<div ng-controller="TestCtrl as test">
  <input type="text" ng-model="test.name" />
  <a ng-click="test.changeName()" href="#">Change Name</a>
</div>  

इस बारे में क्या। $ घड़ी ()? यह मान्य है: यह $ घड़ी ('नाम', ...)
जोआओ पोलो

जवाबों:


160

बस प्रासंगिक संदर्भ को बांधें।

$scope.$watch(angular.bind(this, function () {
  return this.name;
}), function (newVal) {
  console.log('Name changed to ' + newVal);
});

उदाहरण: http://jsbin.com/yinadoce/1/edit

अपडेट करें:

बोगडान गेर्सक का उत्तर वास्तव में एक समान है, दोनों उत्तर thisसही संदर्भ के साथ बाध्यकारी होने का प्रयास करते हैं । हालाँकि, मुझे उसका उत्तर क्लीनर लगा।

कहा गया है कि, सबसे पहले और सबसे महत्वपूर्ण, आपको इसके पीछे अंतर्निहित विचार को समझना होगा

अद्यतन 2:

ईएस 6 का उपयोग करने वालों के लिए, उपयोग करके arrow functionईएस 6 आपको सही संदर्भ ओओटीबी के साथ एक फ़ंक्शन मिलता है।

$scope.$watch(() => this.name, function (newVal) {
  console.log('Name changed to ' + newVal);
});

उदाहरण


9
क्या हम इसे और $ गुंजाइश के मिश्रण से बचने के लिए $ गुंजाइश के बिना इसका उपयोग कर सकते हैं?
मिरोन

4
नहीं जैसा कि मुझे पता है, लेकिन यह पूरी तरह से ठीक है। $scopeआपके लिए एक तरह की सेवा है जो इस तरह के तरीकों की आपूर्ति करती है।
रॉय मिलोह

आप स्पष्ट कर सकते हैं कि क्या nameमें return this.name;नियंत्रक या संपत्ति "के नाम से संबंधित name" यहाँ?
जननिक जोशेम

3
@ जेनिक, angular.bindएक बंधे हुए संदर्भ के साथ एक फ़ंक्शन देता है (arg # 1)। हमारे मामले में, हम बाइंड करते हैं this, जो फ़ंक्शन (arg # 2) के लिए नियंत्रक का उदाहरण है , इसलिए नियंत्रक के उदाहरण की this.nameसंपत्ति nameहै।
रॉय मिलोह

मुझे लगता है कि मैं समझ गया कि यह कैसे काम करता है। जब बाध्य फ़ंक्शन कहा जाता है, तो यह केवल देखे गए मूल्य का मूल्यांकन करता है, है ना?
जननिक जोशेम

138

मैं आमतौर पर ऐसा करता हूं:

controller('TestCtrl', function ($scope) {
    var self = this;

    this.name = 'Max';
    this.changeName = function () {
        this.name = new Date();
   }

   $scope.$watch(function () {
       return self.name;
   },function(value){
        console.log(value)
   });
});

3
मैं मानता हूं कि यह सबसे अच्छा जवाब है, हालांकि मैं यह जोड़ना चाहूंगा कि इस पर भ्रम संभवतः एक फ़ंक्शन को पहले तर्क के रूप में पारित करने $scope.$watchऔर उस फ़ंक्शन का उपयोग बंद करने से एक मूल्य वापस करने के लिए है। मुझे अभी तक इसके एक और उदाहरण पर चलना है, लेकिन यह काम करता है और सबसे अच्छा है। जिस कारण से मैंने नीचे दिए गए उत्तर को नहीं चुना (यानी, $scope.$watch('test.name', function (value) {});) क्योंकि यह आवश्यक है कि मैंने अपने टेम्पलेट में या ui.router के $ स्थितिप्रोवाइडर में अपने नियंत्रक का नाम रखने वाले हार्ड-कोड की आवश्यकता होती है और वहां कोई भी परिवर्तन अनजाने में द्रष्टा को तोड़ देगा।
मॉरिस सिंगर

इसके अलावा, इस उत्तर और वर्तमान में स्वीकृत उत्तर (जो उपयोग करता है angular.bind) के बीच एकमात्र महत्वपूर्ण अंतर यह है कि क्या आप बंद के भीतर thisएक और संदर्भ जोड़ना चाहते हैं या बस जोड़ना चाहते हैं this। ये कार्यात्मक रूप से समकक्ष हैं, और, मेरे अनुभव में, इस तरह की पसंद अक्सर एक व्यक्तिपरक कॉल है और बहुत मजबूत राय की बात है।
मॉरिस सिंगर

1
ES6 के बारे में एक अच्छी बात यह है 2 ऊपर उल्लिखित समाधान करने के लिए सही पाने के लिए होने के उन्मूलन हो जाएगा js गुंजाइश। $scope.$watch( ()=> { return this.name' }, function(){} ) बचाव के लिए वसा तीर
जूसोपि

1
तुम भी बस कर सकते हैं() => this.name
coblr

क्या आप इसके साथ काम कर सकते हैं $scope.$watchCollectionऔर अभी भी oldVal, newValपरम प्राप्त कर सकते हैं?
क्रैकन

23

आप उपयोग कर सकते हैं:

   $scope.$watch("test.name",function(value){
        console.log(value)
   });

यह JSFiddle आपके उदाहरण के साथ काम कर रहा है ।


25
इस दृष्टिकोण के साथ समस्या यह है कि जेएस अब एचटीएमएल पर भरोसा कर रहा है, जिससे नियंत्रक को एक ही नाम (इस मामले में "परीक्षण") के लिए बाध्य किया जा सकता है ताकि $ घड़ी काम करने के लिए हर जगह हो। सूक्ष्म कीड़े को पेश करना बहुत आसान होगा।
jsdw

यह आश्चर्यजनक रूप से काम करने के लिए निकलता है यदि आप कोणीय 1 को कोणीय 2 की तरह लिख रहे हैं जहां सब कुछ एक निर्देश है। Object.observe अभी आश्चर्यजनक होगा।
लैंगडन

13

"TestCtrl से परीक्षण" के रूप में "टेस्ट" का उपयोग करने के समान, जैसा कि एक अन्य उत्तर में वर्णित है, आप "स्व" को अपनी रचना को निर्दिष्ट कर सकते हैं।

controller('TestCtrl', function($scope){
    var self = this;
    $scope.self = self;

    self.name = 'max';
    self.changeName = function(){
            self.name = new Date();
        }

    $scope.$watch("self.name",function(value){
            console.log(value)
        });
})

इस तरह, आप DOM ("TestCtrl as test") में निर्दिष्ट नाम से बंधे नहीं हैं और आपको किसी फ़ंक्शन के लिए .bind (यह) करने की आवश्यकता भी है।

... मूल HTML के साथ उपयोग के लिए निर्दिष्ट:

<div ng-controller="TestCtrl as test">
    <input type="text" ng-model="test.name" />
    <a ng-click="test.changeName()" href="#">Change Name</a>
</div>

बस एक बात जानना चाहते हैं, यानी, $scopeएक सेवा है, इसलिए यदि हम जोड़ते हैं $scope.self = this, तो दूसरे नियंत्रक में, यदि हम ऐसा ही करते हैं , तो वहां क्या होगा?
विवेक कुमार

12

AngularJs 1.5 कंट्रोलर स्ट्रक्चर के लिए डिफ़ॉल्ट $ ctrl का समर्थन करता है।

$scope.$watch("$ctrl.name", (value) => {
    console.log(value)
});

$ WatchGroup का उपयोग करते समय मेरे लिए काम नहीं करता है, क्या यह एक ज्ञात सीमा है? क्या आप इस सुविधा के लिए एक लिंक साझा कर सकते हैं क्योंकि मुझे इसके बारे में कुछ भी नहीं मिल रहा है।
user1852503

@ user1852503 docs.angularjs.org/guide/component तुलना तालिका निर्देश / घटक परिभाषा देखें और 'कंट्रोलर' रिकॉर्ड देखें।
नील्स स्टीनबीक

मैं अब समझता हूँ। आपका जवाब थोड़ा भ्रामक है। पहचानकर्ता $ ctrl एक सुविधा के रूप में नियंत्रक के साथ सहसंबंध नहीं करता है (जैसे $ इंडेक्स उदाहरण के लिए एनजी-रिपीट में), यह बस एक घटक के अंदर नियंत्रक के लिए डिफ़ॉल्ट नाम होता है (और सवाल भी एक के बारे में नहीं है) घटक)।
user1852503

@ user1852503 1) $ ctrl नियंत्रक (नियंत्रक के रूप में) 2) प्रश्न घटकों के बारे में है, क्योंकि इसमें उल्लेख है: "<div ng-नियंत्रक =" TestCtrl को परीक्षण ">"। 3) इस पेज पर सभी awers किसी भी तरह मेरे जवाब के रूप में ही हैं। 4) प्रलेखन के बारे में $ watchGroup $ ctrl.name का उपयोग करते समय बस ठीक काम करना चाहिए क्योंकि यह $ घड़ी पर आधारित है।
Niels Steenbeek

2

आप वास्तव में एक $ घड़ी के पहले तर्क के रूप में एक समारोह में पास कर सकते हैं ():

 app.controller('TestCtrl', function ($scope) {
 this.name = 'Max';

// hmmm, a function
 $scope.$watch(function () {}, function (value){ console.log(value) });
 });

जिसका अर्थ है कि हम अपने इस .नाम संदर्भ को वापस कर सकते हैं:

app.controller('TestCtrl', function ($scope) {
    this.name = 'Max';

    // boom
    $scope.$watch(angular.bind(this, function () {
    return this.name; // `this` IS the `this` above!!
    }), function (value) {
      console.log(value);
    });
});

कंट्रोलर विषय के बारे में एक दिलचस्प पोस्ट पढ़ें https://toddmotto.com/digging-into-angulars-controller-as-syntax/



0

ES6 सिंटैक्स में $ घड़ी लिखना उतना आसान नहीं था जितना मुझे उम्मीद थी। यहाँ आप क्या कर सकते हैं:

// Assuming
// controllerAs: "ctrl"
// or
// ng-controller="MyCtrl as ctrl"
export class MyCtrl {
  constructor ($scope) {
    'ngInject';
    this.foo = 10;
    // Option 1
    $scope.$watch('ctrl.foo', this.watchChanges());
    // Option 2
    $scope.$watch(() => this.foo, this.watchChanges());
  }

  watchChanges() {
    return (newValue, oldValue) => {
      console.log('new', newValue);
    }
  }
}

-1

ध्यान दें : यह तब काम नहीं करता जब व्यू और कंट्रोलर किसी रूट या डायरेक्ट डेफिनिशन ऑब्जेक्ट के माध्यम से युग्मित होते हैं। HTML में "SomeController as SomeCtrl" होने पर केवल वही काम करता है जो नीचे दिखाया गया है। जैसे मार्क वी। नीचे टिप्पणी में बताते हैं, और जैसा वह कहता है कि यह बेहतर है जैसा कि बोगदान करता है।

मैं उपयोग करता हूं: var vm = this;"इस" शब्द को अपने रास्ते से हटाने के लिए नियंत्रक की शुरुआत में। तब vm.name = 'Max';मैं और मैं घड़ी में return vm.name। मैं "vm" का उपयोग वैसे ही करता हूं जैसे @Bogdan "self" का उपयोग करता है। इस संस्करण, यह "vm" या "स्व" की आवश्यकता है क्योंकि शब्द "यह" फ़ंक्शन के अंदर एक अलग संदर्भ लेता है। (इसलिए यह लौटाना। यह काम नहीं करेगा) और हां, आपको $ घड़ी तक पहुंचने के लिए अपने सुंदर "नियंत्रक" में "समाधान" के रूप में $ गुंजाइश इंजेक्ट करने की आवश्यकता है। जॉन पापा की स्टाइल गाइड देखें: https://github.com/johnpapa/angularjs-styleguide#controllers

function SomeController($scope, $log) {
    var vm = this;
    vm.name = 'Max';

    $scope.$watch('vm.name', function(current, original) {
        $log.info('vm.name was %s', original);
        $log.info('vm.name is now %s', current);
    });
}

11
यह तब तक काम करता है जब तक आपके HTML में "SomeController as vm" है। यह भ्रामक है, हालांकि: घड़ी की अभिव्यक्ति में "vm.name" का "var vm = this?" से कोई लेना-देना नहीं है। "नियंत्रक के रूप में" के साथ $ घड़ी का उपयोग करने का एकमात्र सुरक्षित तरीका एक फ़ंक्शन को पहले तर्क के रूप में पारित करना है, जैसा कि बोगडान ऊपर दिखाता है।
मार्क विजसर

-1

यहाँ है कि आप $ स्कोप (और $ वॉच) के बिना ऐसा कैसे करते हैं। टॉप 5 मिस्टेक्स - एब्यूज़िंग वॉच

यदि आप "नियंत्रक" वाक्यविन्यास के रूप में उपयोग कर रहे हैं, तो $ गुंजाइश का उपयोग करने से बचने के लिए यह बेहतर और क्लीनर है।

यहाँ JSFiddle में मेरा कोड है । (मैं नाम रखने के लिए एक सेवा का उपयोग कर रहा हूं, अन्यथा ES5 Object.defineProperty के सेट और तरीकों से अनंत कॉल प्राप्त होते हैं।

var app = angular.module('my-module', []);

app.factory('testService', function() {
    var name = 'Max';

    var getName = function() {
        return name;
    }

    var setName = function(val) {
        name = val;
    }

    return {getName:getName, setName:setName};
});

app.controller('TestCtrl', function (testService) {
    var vm = this;

    vm.changeName = function () {
        vm.name = new Date();
    }

    Object.defineProperty(this, "name", {
        enumerable: true,
        configurable: false,
        get: function() {
            return testService.getName();
        },
        set: function (val) {
            testService.setName(val);
            console.log(vm.name);
        }
    }); 
});

फ़िडल काम नहीं कर रहा है और यह एक वस्तु संपत्ति का निरीक्षण नहीं करेगा।
रूटिकल वी।

@RooticalV। फिडल काम कर रहा है। (यह सुनिश्चित करें कि जब आप AngualrJS चला रहे हों, तो आप लोड टाइप को नोराप-हेड / नॉरैप-बॉडी के रूप में निर्दिष्ट करें
बिनु जसीम

क्षमा करें, लेकिन मैं अभी भी इसे चलाने में कामयाब नहीं हूँ, आपके समाधान के बाद से इस तरह की अफ़सोसनाक बात है
happyZZR1400

@ दुखी सुनिश्चित करें कि आप लाइब्रेरी को Angular 1.4 के रूप में चुनते हैं। (मुझे यकीन नहीं है कि 2.0 काम करेगा) और लोड प्रकार नहीं रैप के रूप में, और रन दबाएं। यह काम करना चाहिए।
बीनू जसीम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.