कोणीय जेएस में नियंत्रकों के बीच डेटा पास करना?


243

मेरे पास एक मूल नियंत्रक है जो मेरे उत्पादों को प्रदर्शित करता है,

App.controller('ProductCtrl',function($scope,$productFactory){
     $productFactory.get().success(function(data){
           $scope.products = data;
     });
});

मेरे विचार में मैं इस उत्पादों को एक सूची में प्रदर्शित कर रहा हूं

<ul>
    <li ng-repeat="product as products">
        {{product.name}}
    </li>
</ul

जब मैं किसी उत्पाद के नाम पर क्लिक करता हूं, तो मेरे पास कार्ट नाम का एक और दृश्य होता है जहां यह उत्पाद जोड़ा जाता है।

 <ul class="cart">
      <li>
          //click one added here
      </li>
      <li>
          //click two added here
      </li>
 </ul>

तो मेरा संदेह यहाँ है, कैसे इस क्लिक किए गए उत्पादों को पहले नियंत्रक से दूसरे में पास किया जाए? मुझे लगता है कि गाड़ी एक नियंत्रक भी होना चाहिए।

मैं निर्देश का उपयोग करके क्लिक इवेंट संभालता हूं। इसके अलावा, मुझे लगता है कि मैं सेवा का उपयोग करना चाहिए ऊपर कार्यक्षमता को प्राप्त करने के लिए बस यह पता नहीं कैसे? क्योंकि कार्ट में जोड़े गए उत्पादों की पूर्वनिर्धारित संख्या 5/10 होगी जो इस बात पर निर्भर करता है कि उपयोगकर्ता किस पृष्ठ पर है। इसलिए मैं इसे सामान्य रखना चाहूंगा।

अपडेट करें:

मैंने प्रसारण के लिए एक सेवा बनाई और दूसरे नियंत्रक में इसे प्राप्त किया। अब क्वेरी है कि मैं डोम को कैसे अपडेट करूं? उत्पाद को छोड़ने के लिए मेरी सूची बहुत कठिन है।


जवाबों:


322

विवरण से, ऐसा लगता है जैसे आपको एक सेवा का उपयोग करना चाहिए। की जाँच करें http://egghead.io/lessons/angularjs-sharing-data-between-controllers और AngularJS सेवा नियंत्रकों के बीच डाटा पासिंग कुछ उदाहरण देखने के लिए।

आप अपनी उत्पाद सेवा को एक कारखाने के रूप में परिभाषित कर सकते हैं:

app.factory('productService', function() {
  var productList = [];

  var addProduct = function(newObj) {
      productList.push(newObj);
  };

  var getProducts = function(){
      return productList;
  };

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});

निर्भरता सेवा को दोनों नियंत्रकों में इंजेक्ट करती है।

अपने में ProductController, कुछ क्रिया को परिभाषित करें जो चयनित ऑब्जेक्ट को सरणी में जोड़ता है:

app.controller('ProductController', function($scope, productService) {
    $scope.callToAddToProductList = function(currObj){
        productService.addProduct(currObj);
    };
});

अपने में CartController, सेवा से उत्पाद प्राप्त करें:

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});

3
जब गेटप्रोडक्ट्स () कहा जाता है तो कार्ट कंट्रोलर एक बार अपडेट करेगा? या हर बार नया उत्पाद जोड़ा जाता है?
किशनियो

1
यदि आप चाहते हैं कि यह स्वचालित रूप से अपडेट हो जाए, तो आप CartCtrl के स्कोप को अपडेट करने के लिए Maxim Shoustin के जवाब और ब्रॉडकास्ट getProducts () $ फंक्शन के भीतर से कॉल को जोड़ सकते हैं।
Chalise

2
@krillgar आप पूरी तरह से सही हैं, शुरू में अनदेखी की गई थी। मैंने एक कार्यशील समाधान को दर्शाने के लिए उत्तर को संपादित किया है।
Chalise

1
@DesheshM हाँ, जैसा कि आप सुझाव देते हैं। आप तरीकों को विस्तार देने पर विचार करना चाह सकते हैं ताकि वे केवल स्मृति में डेटा को धारण न करें और अधिक स्थिर रहें ( $httpउदाहरण के लिए, कॉल के माध्यम से सर्वर पर सहेजें )।
०२

1
उदाहरण के लिए यदि मेरे पास 2 उत्पाद नियंत्रक और 2 गाड़ियां हैं तो क्या होगा? दोनों में तत्व जोड़ा जाएगा? आप इस मामले में कैसे हल करेंगे?
atoth

67

इस क्लिक किए गए उत्पादों को पहले नियंत्रक से दूसरे में कैसे पास करें?

क्लिक पर आप उस विधि को कॉल कर सकते हैं जो प्रसारण को आमंत्रित करती है :

$rootScope.$broadcast('SOME_TAG', 'your value');

और दूसरा कंट्रोलर इस टैग को सुनेगा जैसे:

$scope.$on('SOME_TAG', function(response) {
      // ....
})

चूंकि हम सेवाओं में $ स्कोप को इंजेक्ट नहीं कर सकते हैं, इसलिए सिंगल विलियन स्कोप जैसा कुछ भी नहीं है।

लेकिन हम इंजेक्ट कर सकते हैं $rootScope। इसलिए यदि आप सेवा में मूल्य संग्रहीत करते हैं, तो आप $rootScope.$broadcast('SOME_TAG', 'your value');सेवा निकाय में चला सकते हैं । (सेवाओं के बारे में @Charx विवरण देखें)

app.service('productService',  function($rootScope) {/*....*/}

कृपया $ प्रसारण , $ emit के बारे में अच्छे लेख देखें


1
हाँ, यह आकर्षण की तरह काम करता है मैं कारखाने का उपयोग कर रहा हूँ? बस एक आखिरी चीज है जहां मैं फंस गया हूं मैं हर बार उत्पाद पर क्लिक करने पर नए नियंत्रक में डेटा प्राप्त करता हूं। अब मैं इसे DOM में कैसे अपडेट करूं? क्योंकि मेरे पास पहले से ही सीमाओं के साथ 5 हार्डकोड की सूची है, इसलिए प्रत्येक उत्पाद को उनके अंदर जाने की आवश्यकता है
किशनियो

1
@ टीके - क्या आपको कभी जवाब मिला? यह एक स्पष्ट प्रश्न की तरह लगता है लेकिन मुझे इसका जवाब कहीं नहीं मिल रहा है। मुझे कुछ मूल्य बदलने के लिए एक नियंत्रक चाहिए। जब वह ऐप वैल्यू बदल जाता है तो किसी अन्य सुनने वाले कंट्रोलर को खुद को आवश्यकतानुसार अपडेट करना चाहिए। यह नहीं मिल रहा है।
मूलांक

2
@ अपने q पर उत्तर का प्रकाश डालें। आपके पास कौन सी नियंत्रक संरचना है: समानांतर या बच्चे के माता-पिता। $rootScope.$broadcastसभी नियंत्रकों को सूचित करता है जिनकी समान संरचना उर्फ ​​समान स्तर है।
मैक्सिम शॉटिन

@ उत्तर के लिए धन्यवाद। क्या $ घड़ी का उपयोग करके ऐसा करने का कोई तरीका है? BTW, मेरा समानांतर नियंत्रक है और मुझे आपकी विधि का उपयोग करके काम करने के लिए मिला है। मेरे लिए, जब भी मैं $ घड़ी को जोड़ने की कोशिश करता हूं (यहां तक ​​कि $ rootScope), तो 2 नियंत्रक में $ घड़ी से जुड़ा तरीका केवल पहली बार आग लग जाएगा (2 नियंत्रक का प्रारंभ)। धन्यवाद।
मूलांक

1
हम उपयोग कर सकते हैं $watchअगर मूल्य $rootScopeस्तर पर मौजूद है। अन्यथा केवल प्रसारण अन्य नियंत्रकों को सूचित कर सकता है। FYI करें, यदि अन्य प्रोग्रामर आपके कोड में देखता है broadcast- तर्क स्पष्ट है कि आप क्या करने की कोशिश करते हैं - "प्रसारण घटना"। वैसे भी, मेरे ऍक्स्प से। इसकी नहीं अच्छा अभ्यास का उपयोग करने rootscopeके लिए watch। "आग 1 बार केवल" के बारे में: इस उदाहरण पर एक नज़र डालें: plnkr.co/edit/5zqkj7iYloeHYkzK1Prt?p=preview आपके पास पुराने और नए मूल्य हैं। सुनिश्चित करें कि हर बार जब आपको नया मूल्य मिलता है जो पुराने के बराबर नहीं होता है
मैक्सिम शेट्टिन

24

सेवा बनाने के बिना समाधान, $ rootScope का उपयोग करके:

एप्लिकेशन नियंत्रकों में गुणों को साझा करने के लिए आप Angular $ rootScope का उपयोग कर सकते हैं। यह डेटा साझा करने का एक और विकल्प है, इसे डालना ताकि लोगों को इसके बारे में पता चले।

कंट्रोलर्स के पार कुछ कार्यक्षमता साझा करने का पसंदीदा तरीका एक वैश्विक संपत्ति है जिसे आप $ rootcope का उपयोग करने के लिए पढ़ या बदल सकते हैं।

var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = true;
}]);

app.controller('Ctrl2', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = false;
}]);

टेम्पलेट में $ rootScope का उपयोग करना ($ root के साथ एक्सेस गुण):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>

27
$rootScopeजितना हो सके इससे बचना चाहिए।
शाज़

1
@ शाज आप क्यों विस्तृत कर सकते हैं?
मिरको

5
@ मिर्को आपको वैश्विक स्थिति से जितना हो सके बचने की कोशिश करनी चाहिए क्योंकि कोई भी इसे बदल सकता है-आपके प्रोग्राम की स्थिति को अप्रत्याशित बना सकता है।
उमुत सेवन

4
$ rootScope में वैश्विक स्कोप है, इसलिए देशी वैश्विक वैरिएबल की तरह हमें उन्हें सावधानी से उपयोग करना होगा। यदि कोई नियंत्रक अपने मूल्यों को बदलता है, तो यह वैश्विक दायरे के लिए बदल जाएगा।
संजीव

1
सेवाएँ और फैक्ट्रीज़ दोनों सिंगलटन हैं, लेकिन आप अपने नियंत्रक में किसी भी सेवा को इंजेक्ट करना या न करना चुन सकते हैं। लेकिन सभी चाइल्ड स्कोप रूट्सस्कोप से निकलकर प्रोटोटाइप चेन का अनुसरण करते हैं। इसलिए यदि आप किसी संपत्ति को अपने दायरे में और उसके मौजूद नहीं होने का प्रयास करते हैं तो यह श्रृंखला को देखेगा। संभावना है कि आप अनजाने में जड़ों की संपत्ति में बदलाव कर सकते हैं।
संजीव

16

आप इसे दो तरीकों से कर सकते हैं।

  1. का उपयोग करके $rootscope, लेकिन मैं यह नहीं मानता। सबसे $rootScopeऊपरी गुंजाइश है। एक ऐप में केवल एक ही $rootScopeहो सकता है जिसे ऐप के सभी घटकों के बीच साझा किया जाएगा। इसलिए यह एक वैश्विक चर की तरह काम करता है।

  2. सेवाओं का उपयोग करना। आप दो नियंत्रकों के बीच सेवा साझा करके ऐसा कर सकते हैं। सेवा के लिए कोड इस तरह दिख सकता है:

    app.service('shareDataService', function() {
        var myList = [];
    
        var addList = function(newObj) {
            myList.push(newObj);
        }
    
        var getList = function(){
            return myList;
        }
    
        return {
            addList: addList,
            getList: getList
        };
    });
    

    आप यहाँ मेरी बेला देख सकते हैं ।


और एक 3 विकल्प, आप ईवेंट भेज सकते हैं, सिर्फ सूची में जोड़ने के लिए
DanteTheSmith

यदि उपयोगकर्ता पृष्ठ का उपयोग करता है तो क्या होगा? तब getProducts () आप कुछ नहीं (कर सकते हैं यू यू सभी उपयोगकर्ताओं ताज़ा करने के लिए नहीं बता सकता,?) दे जाएगा!
भट्ट श्रीधर

2
@shreedharbhat पृष्ठ पुनः लोड करने के लिए डेटा को बनाए रखने के बारे में सवाल नहीं पूछ रहा है।
जैक शीशी

9

नियंत्रकों के बीच डेटा साझा करने का एक और भी सरल तरीका नेस्टेड डेटा संरचनाओं का उपयोग करना है। इसके बजाय, उदाहरण के लिए

$scope.customer = {};

हम प्रयोग कर सकते हैं

$scope.data = { customer: {} };

dataसंपत्ति माता पिता दायरे से विरासत में मिला देगा, इसलिए हम अपने खेतों के ऊपर लिख सकता है, अन्य नियंत्रकों से पहुँच रखते हुए।


1
नियंत्रकों को पेरेंट कंट्रोलर्स से अपने स्वयं के दायरे में गुंजाइश गुण प्राप्त होते हैं। स्वच्छ! सादगी इसे
मात देती है

खिचड़ी भाषा यह काम करते हैं। दूसरे नियंत्रक पर मैं $ गुंजाइश का उपयोग करता हूं। डेटा और यह अपरिभाषित है।
बार्ट कैलिक्सो

वह मुझे लगता है कि नेस्टेड नियंत्रकों के बारे में बात कर रहा है। मेरे लिए भी ज्यादा उपयोग नहीं।
नॉर्बर्ट नॉर्बरसन


5

हम सत्र में डेटा को स्टोर कर सकते हैं और इसे आउट प्रोग्राम में कहीं भी उपयोग कर सकते हैं।

$window.sessionStorage.setItem("Mydata",data);

अन्य जगह

$scope.data = $window.sessionStorage.getItem("Mydata");

4

मैंने यहां उत्तर देखे, और यह नियंत्रकों के बीच डेटा साझा करने के प्रश्न का उत्तर दे रहा है, लेकिन मुझे क्या करना चाहिए यदि मैं एक नियंत्रक को दूसरे को इस तथ्य के बारे में सूचित करना चाहता हूं कि डेटा को बदल दिया गया है (प्रसारण का उपयोग किए बिना)? आसान! बस प्रसिद्ध आगंतुक पैटर्न का उपयोग कर:

myApp.service('myService', function() {

    var visitors = [];

    var registerVisitor = function (visitor) {
        visitors.push(visitor);
    }

    var notifyAll = function() {
        for (var index = 0; index < visitors.length; ++index)
            visitors[index].visit();
    }

    var myData = ["some", "list", "of", "data"];

    var setData = function (newData) {
        myData = newData;
        notifyAll();
    }

    var getData = function () {
        return myData;
    }

    return {
        registerVisitor: registerVisitor,
        setData: setData,
        getData: getData
    };
}

myApp.controller('firstController', ['$scope', 'myService',
    function firstController($scope, myService) {

        var setData = function (data) {
            myService.setData(data);
        }

    }
]);

myApp.controller('secondController', ['$scope', 'myService',
    function secondController($scope, myService) {

        myService.registerVisitor(this);

        this.visit = function () {
            $scope.data = myService.getData();
        }

        $scope.data = myService.getData();
    }
]);

इस सरल तरीके से, एक नियंत्रक दूसरे नियंत्रक को अपडेट कर सकता है जिसे कुछ डेटा अपडेट किया गया है।


2
क्या पर्यवेक्षक पैटर्न ( en.wikipedia.org/wiki/Observer_pattern ) यहां अधिक प्रासंगिक नहीं होगा? विज़िटर पैटर्न कुछ और है ... en.wikipedia.org/wiki/Visitor_pattern
Ant Kutschera

3

मैंने एक कारखाना बनाया है जो मार्ग पथ के पैटर्न के बीच साझा दायरे को नियंत्रित करता है, इसलिए आप साझा डेटा को केवल तब बनाए रख सकते हैं जब उपयोगकर्ता उसी मार्ग मूल पथ में नेविगेट कर रहे हों।

.controller('CadastroController', ['$scope', 'RouteSharedScope',
    function($scope, routeSharedScope) {
      var customerScope = routeSharedScope.scopeFor('/Customer');
      //var indexScope = routeSharedScope.scopeFor('/');
    }
 ])

इसलिए, यदि उपयोगकर्ता किसी अन्य मार्ग पथ पर जाता है, उदाहरण के लिए '/ सहायता', पथ '/ ग्राहक' के लिए साझा किया गया डेटा स्वचालित रूप से नष्ट हो जाएगा। लेकिन, अगर इसके बजाय उपयोगकर्ता 'बच्चे' के रास्ते पर जाता है, जैसे '/ ग्राहक / 1' या '/ ग्राहक / सूची' गुंजाइश नष्ट नहीं होगी।

आप यहां एक नमूना देख सकते हैं: http://plnkr.co/edit/OL8of9


3

1

using $localStorage

app.controller('ProductController', function($scope, $localStorage) {
    $scope.setSelectedProduct = function(selectedObj){
        $localStorage.selectedObj= selectedObj;
    };
});

app.controller('CartController', function($scope,$localStorage) { 
    $scope.selectedProducts = $localStorage.selectedObj;
    $localStorage.$reset();//to remove
});

2

क्लिक पर आप उस विधि को कॉल कर सकते हैं जो प्रसारण को आमंत्रित करती है:

$rootScope.$broadcast('SOME_TAG', 'your value');

and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
      // ....
})

3

using $rootScope:

4

window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");

5

कोणीय सेवा का उपयोग करने का एक तरीका:

var app = angular.module("home", []);

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});

app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});

2
अपने उत्तर में कुछ और स्पष्टीकरण दें।
गेरहार्ड बार्नार्ड

2

अपने मॉड्यूल में एक कारखाना बनाएं और नियंत्रक में कारखाने का एक संदर्भ जोड़ें और नियंत्रक में इसके चर का उपयोग करें और अब संदर्भ को जोड़कर किसी अन्य नियंत्रक में डेटा का मूल्य प्राप्त करें जहां आप कभी भी चाहते हैं


2

मुझे नहीं पता कि यह किसी की मदद करेगा, लेकिन चारैक्स (धन्यवाद!) के आधार पर मैंने सरल कैश सेवा बनाई है। बेझिझक, रीमिक्स और साझा करें:

angular.service('cache', function() {
    var _cache, _store, _get, _set, _clear;
    _cache = {};

    _store = function(data) {
        angular.merge(_cache, data);
    };

    _set = function(data) {
        _cache = angular.extend({}, data);
    };

    _get = function(key) {
        if(key == null) {
            return _cache;
        } else {
            return _cache[key];
        }
    };

    _clear = function() {
        _cache = {};
    };

    return {
        get: _get,
        set: _set,
        store: _store,
        clear: _clear
    };
});

2

कोणीय सेवा का उपयोग करने का एक तरीका:

var app = angular.module("home", []);

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});


app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});



<div ng-app='home'>

<div ng-controller='one'>
  Type in text: 
  <input type='text' ng-model="inputText.o"/>
</div>
<br />

<div ng-controller='two'>
  Type in text:
  <input type='text' ng-model="inputTextTwo.o"/>
</div>

</div>

https://jsfiddle.net/1w64222q/


1

FYI करें $ स्कोप ऑब्जेक्ट में $ emit, $ ब्रॉडकास्ट, $ on और The $ rootScope ऑब्जेक्ट में समान $ emit, $ ब्रॉडकास्ट, $ है

यहाँ कोणीय में प्रकाशन / सदस्यता पैटर्न के बारे में अधिक पढ़ें


1

$ प्रसारण का उपयोग करके @Maxim द्वारा प्रस्तावित समाधान में सुधार करने के लिए, डेटा न भेजें

$rootScope.$broadcast('SOME_TAG', 'my variable');

लेकिन डेटा सुनने के लिए

$scope.$on('SOME_TAG', function(event, args) {
    console.log("My variable is", args);// args is value of your variable
})

1

इसे करने के तीन तरीके हैं,

a) किसी सेवा का उपयोग करना

ख) नियंत्रक स्कोप के बीच माता-पिता / बच्चे के संबंध के आधार पर शोषण।

c) Angular 2.0 में "As" कीवर्ड डेटा को एक कंट्रोलर से दूसरे में पास करेगा।

उदाहरण के लिए अधिक जानकारी के लिए, कृपया नीचे दिए गए लिंक की जाँच करें:

http://www.tutespace.com/2016/03/angular-js.html


0
var custApp = angular.module("custApp", [])
.controller('FirstController', FirstController)
.controller('SecondController',SecondController)
.service('sharedData', SharedData);

FirstController.$inject = ['sharedData'];
function FirstController(sharedData) {
this.data = sharedData.data;
}

SecondController.$inject['sharedData'];
function SecondController(sharedData) {
this.data = sharedData.data;
}

function SharedData() {
this.data = {
    value: 'default Value'
}
}

पहला नियंत्रक

<div ng-controller="FirstController as vm">
<input type=text ng-model="vm.data.value" />
</div>

दूसरा नियंत्रक

 <div ng-controller="SecondController as vm">
    Second Controller<br>
    {{vm.data.value}}
</div>

-1

मुझे लगता है

सबसे अच्छा तरीका

$ लोकलस्टोरेज का उपयोग करना है। (हर समय काम करता है)

app.controller('ProductController', function($scope, $localStorage) {
    $scope.setSelectedProduct = function(selectedObj){
        $localStorage.selectedObj= selectedObj;
    };
});

आपका कार्डकंट्रोलर होगा

app.controller('CartController', function($scope,$localStorage) { 
    $scope.selectedProducts = $localStorage.selectedObj;
    $localStorage.$reset();//to remove
});

आप भी जोड़ सकते हैं

if($localStorage.selectedObj){
    $scope.selectedProducts = $localStorage.selectedObj;
}else{
    //redirect to select product using $location.url('/select-product')
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.