झिलमिलाहट को रोकने के लिए लोड किए गए मॉडल तक एंगुलरजेएस मार्ग में परिवर्तन


321

मुझे आश्चर्य हो रहा है कि क्या एंगुलरजेएस के लिए एक रास्ता (जीमेल के समान) है जब तक कि प्रत्येक मॉडल के बाद एक नया मार्ग दिखाने में देरी न हो और इसका डेटा अपनी संबंधित सेवाओं का उपयोग करके लाया गया हो

उदाहरण के लिए, यदि कोई ProjectsControllerसूचीबद्ध सभी प्रोजेक्ट्स थे और project_index.htmlजो इन प्रोजेक्ट्स को Project.query()दिखाने वाला टेम्पलेट था, तो नया पेज दिखाने से पहले पूरी तरह से प्राप्त किया जाएगा।

तब तक, पुराना पृष्ठ अभी भी प्रदर्शित होता रहेगा (उदाहरण के लिए, यदि मैं दूसरा पृष्ठ ब्राउज़ कर रहा था और फिर इस प्रोजेक्ट इंडेक्स को देखने का निर्णय लिया गया)।

जवाबों:


374

$ pathProvider संकल्प संपत्ति डेटा के लोड होने तक मार्ग परिवर्तन में देरी की अनुमति देता है।

पहले resolveइस तरह की विशेषता वाले मार्ग को परिभाषित करें।

angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/phones', {
        templateUrl: 'partials/phone-list.html', 
        controller: PhoneListCtrl, 
        resolve: PhoneListCtrl.resolve}).
      when('/phones/:phoneId', {
        templateUrl: 'partials/phone-detail.html', 
        controller: PhoneDetailCtrl, 
        resolve: PhoneDetailCtrl.resolve}).
      otherwise({redirectTo: '/phones'});
}]);

ध्यान दें कि resolveसंपत्ति मार्ग पर परिभाषित की गई है।

function PhoneListCtrl($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}

PhoneListCtrl.resolve = {
  phones: function(Phone, $q) {
    // see: https://groups.google.com/forum/?fromgroups=#!topic/angular/DGf7yyD4Oc4
    var deferred = $q.defer();
    Phone.query(function(successData) {
            deferred.resolve(successData); 
    }, function(errorData) {
            deferred.reject(); // you could optionally pass error data here
    });
    return deferred.promise;
  },
  delay: function($q, $defer) {
    var delay = $q.defer();
    $defer(delay.resolve, 1000);
    return delay.promise;
  }
}

ध्यान दें कि नियंत्रक परिभाषा में एक रिज़ॉल्यूशन ऑब्जेक्ट होता है जो उन चीजों की घोषणा करता है जो कंट्रोलर कंस्ट्रक्टर को उपलब्ध होनी चाहिए। यहां phonesनियंत्रक में अंतःक्षिप्त है और इसे resolveसंपत्ति में परिभाषित किया गया है।

resolve.phonesसमारोह एक वादा लौटने के लिए जिम्मेदार है। सभी वादे एकत्र किए जाते हैं और मार्ग परिवर्तन में देरी होती है जब तक कि सभी वादों को हल नहीं किया जाता है।

वर्किंग डेमो: http://mhevery.github.com/angular-phonecat/app/#/phones स्रोत: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b3b5d3d531619bf901534968316893131


10
@MiskoHevery - क्या होगा यदि आपके नियंत्रक एक मॉड्यूल के अंदर हैं और फ़ंक्शन के बजाय एक स्ट्रिंग के रूप में परिभाषित हैं। तुम जैसे कैसे संकल्प विशेषता सेटअप कर सकता है?
a00n

53
इसका उपयोग angular.controller()प्रकार नियंत्रक परिभाषाओं में कैसे किया जाता है ? में $routeProviderसामान, मैंने सोचा कि आप नियंत्रकों की स्ट्रिंग के नाम का इस्तेमाल किया था।
बेन लैश

6
कोणीय.कंट्रोलर () और AngularJS के नवीनतम संस्करण के साथ कोई उदाहरण?
लॉरेंट

22
@ पत्थर, जब आप उपयोग करते हैं angular.controller(), तो आप इस फ़ंक्शन के परिणाम को एक चर ( var MyCtrl = angular.controller(...)) पर असाइन कर सकते हैं और फिर उस पर आगे काम कर सकते हैं ( MyCtrl.loadData = function(){..})। एगहेड के वीडियो की जांच करें, कोड को सीधे वहां दिखाया गया है: एगहेड.आईओ
विडियो

17
मैं अभी भी एक अच्छा तरीका एक वैश्विक में अपने नियंत्रक जगह के बिना के साथ करना चाहते हैं। मैं सभी जगहों पर ग्लोबल्स से जूझना नहीं चाहता। आप इसे एक निरंतरता के साथ कर सकते हैं, लेकिन यह अच्छा होगा कि आप रेजोल्यूशन फंक्शन को कंट्रोलर पर / कहीं और न करें।
एरिक होन

51

यहाँ एक न्यूनतम काम करने का उदाहरण है जो कोणीय 1.0.2 के लिए काम करता है

टेम्पलेट:

<script type="text/ng-template" id="/editor-tpl.html">
    Editor Template {{datasets}}
</script>

<div ng-view>

</div>

जावास्क्रिप्ट:

function MyCtrl($scope, datasets) {    
    $scope.datasets = datasets;
}

MyCtrl.resolve = {
    datasets : function($q, $http) {
        var deferred = $q.defer();

        $http({method: 'GET', url: '/someUrl'})
            .success(function(data) {
                deferred.resolve(data)
            })
            .error(function(data){
                //actually you'd want deffered.reject(data) here
                //but to show what would happen on success..
                deferred.resolve("error value");
            });

        return deferred.promise;
    }
};

var myApp = angular.module('myApp', [], function($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/editor-tpl.html',
        controller: MyCtrl,
        resolve: MyCtrl.resolve
    });
});​

http://jsfiddle.net/dTJ9N/3/

सुव्यवस्थित संस्करण:

चूंकि $ http () पहले से ही एक वादा (उर्फ स्थगित) लौटाता है, हमें वास्तव में अपना खुद का बनाने की आवश्यकता नहीं है। तो हम MyCtrl को सरल बना सकते हैं। इसका समाधान करें:

MyCtrl.resolve = {
    datasets : function($http) {
        return $http({
            method: 'GET', 
            url: 'http://fiddle.jshell.net/'
        });
    }
};

$ Http () के परिणाम में डेटा , स्थिति , हेडर और कॉन्फ़िगर ऑब्जेक्ट शामिल हैं, इसलिए हमें MyCtrl के शरीर को बदलना होगा:

$scope.datasets = datasets.data;

http://jsfiddle.net/dTJ9N/5/


मैं ऐसा कुछ करने की कोशिश कर रहा हूं लेकिन 'डेटासेट' को इंजेक्ट करने में परेशानी हो रही है क्योंकि यह परिभाषित नहीं है। कोई विचार?
रोब ब्यारग्वे

हे mb21, मुझे लगता है कि आप इस प्रश्न के साथ मेरी मदद करने में सक्षम हो सकते हैं: stackoverflow.com/questions/14271713/…
winduptoy

क्या कोई मुझे इस उत्तर को app.controller ('MyCtrl') प्रारूप में बदलने में मदद कर सकता है? jsfiddle.net/5usya/1 ने मेरे लिए काम नहीं किया।
user1071182

मुझे एक त्रुटि मिलती है:Unknown provider: datasetsProvider <- datasets
chovy

आप इसके साथ डेटासेट को बदलकर अपना उत्तर सरल बना सकते हैं:function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
मोर्टेज़ा टूरानी

32

मैं कुछ लोगों को यह पूछते हुए देखता हूं कि यह न्यूनतम अनुकूलता इंजेक्शन के साथ कोणीय.कंट्रोलर पद्धति का उपयोग करके कैसे किया जाता है। जब से मुझे यह काम मिला है मैंने महसूस किया कि मैं वापस आकर मदद करने के लिए बाध्य हूं। यहाँ मेरा समाधान (मूल प्रश्न और मिस्को के उत्तर से अपनाया गया है):

angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/phones', {
        templateUrl: 'partials/phone-list.html', 
        controller: PhoneListCtrl, 
        resolve: { 
            phones: ["Phone", "$q", function(Phone, $q) {
                var deferred = $q.defer();
                Phone.query(function(successData) {
                  deferred.resolve(successData); 
                }, function(errorData) {
                  deferred.reject(); // you could optionally pass error data here
                });
                return deferred.promise;
             ]
            },
            delay: ["$q","$defer", function($q, $defer) {
               var delay = $q.defer();
               $defer(delay.resolve, 1000);
               return delay.promise;
              }
            ]
        },

        }).
      when('/phones/:phoneId', {
        templateUrl: 'partials/phone-detail.html', 
        controller: PhoneDetailCtrl, 
        resolve: PhoneDetailCtrl.resolve}).
      otherwise({redirectTo: '/phones'});
}]);

angular.controller("PhoneListCtrl", [ "$scope", "phones", ($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}]);

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

मैं इस youtube वीडियो की सिफारिश भी करता हूं। http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , जिसने मुझे काफी मदद की

क्या आपको दिलचस्पी है कि मैंने अपना कोड (कॉफ़ीस्क्रिप्ट में लिखा हुआ) भी पेस्ट करने का फैसला किया है ताकि आप देख सकें कि मुझे यह कैसे काम कर रहा है।

FYI करें, अग्रिम में मैं एक सामान्य नियंत्रक का उपयोग करता हूँ जो मुझे कई मॉडलों पर CRUD करने में मदद करता है:

appModule.config ['$routeProvider', ($routeProvider) ->
  genericControllers = ["boards","teachers","classrooms","students"]
  for controllerName in genericControllers
    $routeProvider
      .when "/#{controllerName}/",
        action: 'confirmLogin'
        controller: 'GenericController'
        controllerName: controllerName
        templateUrl: "/static/templates/#{controllerName}.html"
        resolve:
          items : ["$q", "$route", "$http", ($q, $route, $http) ->
             deferred = $q.defer()
             controllerName = $route.current.controllerName
             $http(
               method: "GET"
               url: "/api/#{controllerName}/"
             )
             .success (response) ->
               deferred.resolve(response.payload)
             .error (response) ->
               deferred.reject(response.message)

             return deferred.promise
          ]

  $routeProvider
    .otherwise
      redirectTo: '/'
      action: 'checkStatus'
]

appModule.controller "GenericController", ["$scope", "$route", "$http", "$cookies", "items", ($scope, $route, $http, $cookies, items) ->

  $scope.items = items
      #etc ....
    ]

क्या मैं आपके उदाहरण से सही ढंग से अनुमान लगाता हूं और मेरे असफल प्रयास यह है कि अब एंगुलर के resolveहाल के संस्करणों में नियंत्रक में किसी फ़ंक्शन को संदर्भित करना असंभव है ? तो यह सही है कि यह यहाँ है क्योंकि यह विन्यास में घोषित किया जाना है?
XML

@XMLilley मुझे पूरा यकीन है कि यह मामला है। यह उदाहरण 1.1.2 से था जब मैंने इसे लिखा था, मुझे विश्वास है। मुझे कंट्रोलर के अंदर
रिज़ॉल्यूशन

2
अच्छा है धन्यवाद। एसओ पर ऐसा करने के बहुत सारे उदाहरण हैं (यहाँ शीर्ष दो की तरह), लेकिन वे 2012 से और 2013 की शुरुआत तक सभी हैं। यह एक सुंदर दृष्टिकोण है, लेकिन यह पदावनत प्रतीत होता है। सबसे साफ विकल्प अब व्यक्तिगत सेवाओं को लिखने के लिए लगता है जो वादे की वस्तुएं हैं।
एक्सएमएल

धन्यवाद यह मेरे लिए काम किया। किसी अन्य व्यक्ति के लिए जो अपरिभाषित $deferसेवा के बारे में त्रुटियां प्राप्त करता है, कृपया ध्यान दें कि AngularJS के संस्करण 1.5.7 में, आप $timeoutइसके बजाय उपयोग करना चाहते हैं ।
racl101

18

यह वचन , जो कि 1.1.5 और उसके बाद के संस्करण का हिस्सा है, की $promiseवस्तु को उजागर करता है $resource। NgResource के संस्करण इस सहित इस तरह से संसाधनों को हल करने की अनुमति देते हैं:

$ routeProvider

resolve: {
    data: function(Resource) {
        return Resource.get().$promise;
    }
}

नियंत्रक

app.controller('ResourceCtrl', ['$scope', 'data', function($scope, data) {

    $scope.data = data;

}]);

कृपया कौन से संस्करण शामिल हैं?
XML

नवीनतम अस्थिर संस्करण (1.1.5) में यह प्रतिबद्धता शामिल है। ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js
मैक्सिमिलियन हॉफमैन

मुझे यह कम वाचाल दृष्टिकोण पसंद है। वास्तविक डेटा ऑब्जेक्ट से एक वादा बनाना और सीधे में पास करना अच्छा होगा, लेकिन यह इतना कम कोड है कि यह अच्छी तरह से काम करता है।
सैम बरनम

1
संसाधन $ मार्गप्रेमों तक कैसे पहुँचेगा? उदाहरण के लिए: in GET '/api/1/apps/:appId'-> App.get({id: $routeParams.appId}).$promise();मैं इस तरह का उपयोग नहीं कर सकता
zeronone

2
@ एक्सोनोन आप $routeअपने संकल्प और उपयोग के लिए इंजेक्ट करते हैं $route.current.params। सावधान रहें, $routeParamsअभी भी पुराने मार्ग की ओर इशारा कर रहा है।
ब्राइस स्टेसी

16

यह स्निपेट डिपेंडेंसी इंजेक्शन फ्रेंडली है (मैं इसे एनक्मिन और कुसुइल के संयोजन में भी उपयोग करता हूं ) और यह एक अधिक सुरुचिपूर्ण डोमेन संचालित समाधान है।

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

नोट: यदि आप ngmin का उपयोग कर रहे हैं (और यदि आप नहीं कर रहे हैं: आपको चाहिए) तो आपको केवल DI सरणी सम्मेलन के साथ संकल्प कार्यों को लिखना होगा।

angular.module('myApp').factory('Phone',function ($resource) {
  return $resource('/api/phone/:id', {id: '@id'});
}).constant('phoneRoutes', {
    '/phone': {
      templateUrl: 'app/phone/index.tmpl.html',
      controller: 'PhoneIndexController'
    },
    '/phone/create': {
      templateUrl: 'app/phone/edit.tmpl.html',
      controller: 'PhoneEditController',
      resolve: {
        phone: ['$route', 'Phone', function ($route, Phone) {
          return new Phone();
        }]
      }
    },
    '/phone/edit/:id': {
      templateUrl: 'app/phone/edit.tmpl.html',
      controller: 'PhoneEditController',
      resolve: {
        form: ['$route', 'Phone', function ($route, Phone) {
          return Phone.get({ id: $route.current.params.id }).$promise;
        }]
      }
    }
  });

अगला टुकड़ा राउटिंग डेटा को इंजेक्ट कर रहा है जब मॉड्यूल कॉन्फ़िगर राज्य में है और इसे $ मार्गप्रोपाइडर पर लागू करना है ।

angular.module('myApp').config(function ($routeProvider, 
                                         phoneRoutes, 
                                         /* ... otherRoutes ... */) {

  $routeProvider.when('/', { templateUrl: 'app/main/index.tmpl.html' });

  // Loop through all paths provided by the injected route data.

  angular.forEach(phoneRoutes, function(routeData, path) {
    $routeProvider.when(path, routeData);
  });

  $routeProvider.otherwise({ redirectTo: '/' });

});

इस सेटअप के साथ मार्ग विन्यास का परीक्षण भी बहुत आसान है:

describe('phoneRoutes', function() {

  it('should match route configuration', function() {

    module('myApp');

    // Mock the Phone resource
    function PhoneMock() {}
    PhoneMock.get = function() { return {}; };

    module(function($provide) {
      $provide.value('Phone', FormMock);
    });

    inject(function($route, $location, $rootScope, phoneRoutes) {
      angular.forEach(phoneRoutes, function (routeData, path) {

        $location.path(path);
        $rootScope.$digest();

        expect($route.current.templateUrl).toBe(routeData.templateUrl);
        expect($route.current.controller).toBe(routeData.controller);
      });
    });
  });
});

आप इसे मेरे नवीनतम (आगामी) प्रयोग में पूरे गौरव से देख सकते हैं । यद्यपि यह विधि मेरे लिए ठीक काम करती है, मैं वास्तव में आश्चर्यचकित हूं कि क्यों $ इंजेक्टर किसी भी चीज के निर्माण में देरी नहीं कर रहा है जब वह किसी भी चीज के इंजेक्शन का पता लगाता है जो एक वादा वस्तु है; यह बहुत आसान soooOOOOOooOOOOO बातें करना होगा।

संपादित करें: इस्तेमाल किया कोणीय v1.2 (rc2)


2
यह उत्कृष्ट उत्तर "कोणीय" दर्शन (एनकैप्सुलेशन, आदि) के अनुरूप अधिक लगता है। हम सभी को कुडज़ू जैसे कोडबेस पर तर्क को रोकने के लिए एक सचेत प्रयास करना चाहिए।
झाकियाँ

I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise objectमुझे लगता है कि वे इस कार्यक्षमता को छोड़ दिया है क्योंकि यह डिजाइन पैटर्न को प्रोत्साहित कर सकता है जो क्षुधा की जवाबदेही को नकारात्मक रूप से प्रभावित करता है। उनके दिमाग में आदर्श ऐप वह है जो वास्तव में अतुल्यकालिक है, इसलिए हल करना एक किनारे का मामला होना चाहिए।
रात्रि २३:३३ तक

11

मार्ग दिखाने में देरी करना एक अतुल्यकालिक उलझन का नेतृत्व करने के लिए निश्चित है ... क्यों नहीं बस अपनी मुख्य इकाई की लोडिंग स्थिति को ट्रैक करें और इसे देखने में उपयोग करें। अपने नियंत्रक में उदाहरण के लिए आप ngResource पर सफलता और त्रुटि कॉलबैक दोनों का उपयोग कर सकते हैं:

$scope.httpStatus = 0; // in progress
$scope.projects = $resource.query('/projects', function() {
    $scope.httpStatus = 200;
  }, function(response) {
    $scope.httpStatus = response.status;
  });

तब देखने में आप जो कुछ भी कर सकते थे:

<div ng-show="httpStatus == 0">
    Loading
</div>
<div ng-show="httpStatus == 200">
    Real stuff
    <div ng-repeat="project in projects">
         ...
    </div>
</div>
<div ng-show="httpStatus >= 400">
    Error, not found, etc. Could distinguish 4xx not found from 
    5xx server error even.
</div>

6
शायद HTTP स्थिति को देखने के लिए उजागर करना सही नहीं है, सीएसएस वर्गों और डोम तत्वों से निपटने की तुलना में नियंत्रक में हैं। मैं शायद एक ही विचार का उपयोग करूँगा, लेकिन अलग स्थिति isValid () और isLoaded () में।
jpsimons

1
यह वास्तव में चिंताओं का सबसे अच्छा पृथक्करण नहीं है, साथ ही अगर आप नेस्टेड नियंत्रकों के पास हैं जो विशिष्ट ऑब्जेक्ट पर निर्भर करते हैं तो यह दुर्घटनाग्रस्त हो जाएगा।
null

यह बहुत चालाक है .. देखने के लिए स्थिति कोड को उजागर करने के रूप में, आप नियंत्रक के भीतर गुंजाइश गुणों में http तर्क को चिपका सकते हैं, फिर उन्हें बांध सकते हैं। यदि आप पृष्ठभूमि में होने वाली कई अजाक्स कॉल कर रहे हैं, तो आप वैसे भी ऐसा करना चाहेंगे।
KingOfHypocrites

यह ठीक होगा यदि मुद्दा केवल एक दृश्य में देरी का मामला था। लेकिन अगर आप एक नियंत्रक की तात्कालिकता में देरी करने की आवश्यकता है, तो समाधान का सबसे अच्छा उपयोग किया जाता है - केवल दृश्य नहीं। (पूर्व: यदि आपको यह सुनिश्चित करने की आवश्यकता है कि आपका JSON लोड हो गया है क्योंकि आपका नियंत्रक इसे वायर होने से पहले एक निर्देश के पास भेज देता है।) डॉक्स से: "राउटर उन सभी के हल होने का इंतजार करेगा या नियंत्रक से पहले एक को खारिज कर दिया जाएगा। तात्कालिक ”।
दान

8

मैंने ऊपर मिसको के कोड से काम किया है और यही मैंने इसके साथ किया है। यह एक अधिक वर्तमान समाधान है क्योंकि $deferइसे बदल दिया गया है $timeout। स्थानापन्न $timeoutहालांकि, समय समाप्ति की अवधि के लिए इंतजार करेंगे (Misko के कोड, 1 सेकंड में) तो उम्मीद यह समय में हल हो जाए तो डेटा वापस। इस तरह से, यह asap लौटता है।

function PhoneListCtrl($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}

PhoneListCtrl.resolve = {

  phones: function($q, Phone) {
    var deferred = $q.defer();

    Phone.query(function(phones) {
        deferred.resolve(phones);
    });

    return deferred.promise;
  }
}

7

AngularJS 1.1.5 का उपयोग करना

AngularJS 1.1.5 का उपयोग करके जस्टिन के जवाब में 'फोन' फ़ंक्शन को अपडेट करना सिंटैक्स ।

मूल:

phones: function($q, Phone) {
    var deferred = $q.defer();

    Phone.query(function(phones) {
        deferred.resolve(phones);
    });

    return deferred.promise;
}

अपडेट किया गया:

phones: function(Phone) {
    return Phone.query().$promise;
}

कोणीय टीम और योगदानकर्ताओं के लिए बहुत कम धन्यवाद। :)

मैक्सिमिलियन हॉफमैन का जवाब भी यही है। जाहिर है कि कमिटमेंट ने इसे 1.1.5 कर दिया।


1
मुझे डॉक्स के बारे $promiseमें कुछ भी पता नहीं लग सकता है । इसे v2.0 + के रूप में निकाला जा सकता है।
रात्रि

यह केवल 1.2
थॉमस

5

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

angular.module('app', ['ngRoute']).
  config(['$routeProvider', function($routeProvider, EntitiesCtrlResolve, EntityCtrlResolve) {
    $routeProvider.
      when('/entities', {
        templateUrl: 'entities.html', 
        controller: 'EntitiesCtrl', 
        resolve: EntitiesCtrlResolve
      }).
      when('/entity/:entityId', {
        templateUrl: 'entity.html', 
        controller: 'EntityCtrl', 
        resolve: EntityCtrlResolve
      }).
      otherwise({redirectTo: '/entities'});
}]);

ध्यान दें कि resolveसंपत्ति मार्ग पर परिभाषित की गई है।

EntitiesCtrlResolveऔर EntityCtrlResolveहै निरंतर रूप में एक ही फाइल में परिभाषित वस्तुओं EntitiesCtrlऔर EntityCtrlनियंत्रकों।

// EntitiesCtrl.js

angular.module('app').constant('EntitiesCtrlResolve', {
  Entities: function(EntitiesService) {
    return EntitiesService.getAll();
  }
});

angular.module('app').controller('EntitiesCtrl', function(Entities) {
  $scope.entities = Entities;

  // some code..
});

// EntityCtrl.js

angular.module('app').constant('EntityCtrlResolve', {
  Entity: function($route, EntitiesService) {
    return EntitiesService.getById($route.current.params.projectId);
  }
});

angular.module('app').controller('EntityCtrl', function(Entity) {
  $scope.entity = Entity;

  // some code..
});

3

मुझे डार्क रिपोर्टर का आइडिया पसंद है क्योंकि एक देव टीम के लिए एंगुलरजेएस के लिए नया समझना आसान होगा और सीधे काम करना होगा।

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

$ क्षेत्र में 'तैयार' ध्वज जोड़ें:

$http({method: 'GET', url: '...'}).
    success(function(data, status, headers, config) {
        $scope.dataForView = data;      
        $scope.ready = true;  // <-- set true after loaded
    })
});

HTML दृश्य में:

<div ng-show="!ready">

    <!-- Show loading graphic, e.g. Twitter Boostrap progress bar -->
    <div class="progress progress-striped active">
        <div class="bar" style="width: 100%;"></div>
    </div>

</div>

<div ng-show="ready">

    <!-- Real content goes here and will appear after loading -->

</div>

इसे भी देखें: Boostrap प्रगति बार डॉक्स


यदि आप डेटा के कई टुकड़े लोड कर रहे हैं, तो थोड़ा अलग करें। कैसे पता चलेगा कि सब कुछ लोड है?
टॉक्सिक

जब से मैंने इस उत्तर को फ़रवरी में जोड़ा है, इस पृष्ठ पर बहुत अधिक गतिविधि के साथ चीजें आगे बढ़ी हैं। लगता है कि इस समस्या को हल करने के लिए कोणीय में बेहतर समर्थन है, जो यहां सुझाया गया है। चीयर्स,
रेग्युडविन

मैं थोड़ी देर से पहुंचता हूं, लेकिन डेटा के कई टुकड़ों से निपटना बड़ी चिंता का विषय नहीं है। आपको प्रत्येक अनुरोध के लिए बस अलग-अलग चर (बूलियन: isReadyData1, isReadyData2 आदि) का उपयोग करना होगा और $ गुंजाइश सेट करनी होगी। पहले से ही = isReadyData1 && isReadyData2 ...; मेरे लिए अच्छा काम करता है।
गुइलूमेअ

1

मुझे उपरोक्त उत्तर पसंद आए और मैंने उनसे बहुत कुछ सीखा लेकिन ऐसा कुछ है जो उपरोक्त अधिकांश उत्तरों में गायब है।

मैं एक समान परिदृश्य में फंस गया था जहां मैं कुछ डेटा के साथ url को हल कर रहा था जो सर्वर से पहले अनुरोध में प्राप्त होता है। समस्या यह है कि अगर वादा किया गया था, तो मुझे सामना करना पड़ा rejected

मैं एक कस्टम प्रोवाइडर का उपयोग कर रहा था जो कि लौटाता Promiseथा जो कि द्वारा हल किया गया resolveथा$routeProvider config चरण के समय में।

मैं यहां तनाव करना चाहता हूं कि whenयह अवधारणा कुछ इस तरह की है।

यह url बार में url देखता है और फिर संबंधित whenकंट्रोलर और व्यू में संबंधित ब्लॉक को अब तक अच्छा बताया जाता है।

आइए हम कहते हैं कि मेरे पास निम्नलिखित चरण चरण हैं।

App.when('/', {
   templateUrl: '/assets/campaigns/index.html',
   controller: 'CampaignListCtr',
   resolve : {
      Auth : function(){
         return AuthServiceProvider.auth('campaign');
      }
   }
})
// Default route
.otherwise({
   redirectTo: '/segments'
});

ब्राउज़र में रूट यूआरएल पर रन का पहला ब्लॉक कहा जाता है अन्यथा otherwiseकहा जाता है।

आइए कल्पना करें कि मैंने पता बार AuthServicePrivider.auth()फ़ंक्शन में रूट यूआरएल को हिट किया है जिसे कॉल किया जाता है।

कहते हैं कि वादा किया गया राज्य अस्वीकार है तो फिर क्या ???

कुछ भी प्रदान नहीं किया जाता है।

Otherwise ब्लॉक को निष्पादित नहीं किया जाएगा क्योंकि यह किसी भी यूआरएल के लिए है जो कॉन्फिगर ब्लॉक में परिभाषित नहीं है और कोणीयजेएस कॉन्फिग चरण के लिए अज्ञात है।

हमें उस घटना को संभालना होगा जो इस वादे के हल नहीं होने पर निकाल दी जाती है। असफलता $routeChangeErorrपर निकाल दिया जाता है $rootScope

इसे नीचे दिए गए कोड के अनुसार दिखाया जा सकता है।

$rootScope.$on('$routeChangeError', function(event, current, previous, rejection){
    // Use params in redirection logic.
    // event is the routeChangeEvent
    // current is the current url
    // previous is the previous url
    $location.path($rootScope.rootPath);
});

IMO आमतौर पर एप्लिकेशन के रन ब्लॉक में इवेंट ट्रैकिंग कोड डालना एक अच्छा विचार है। यह कोड एप्लिकेशन के कॉन्फ़िगरेशन चरण के ठीक बाद चलता है।

App.run(['$routeParams', '$rootScope', '$location', function($routeParams, $rootScope, $location){
   $rootScope.rootPath = "my custom path";
   // Event to listen to all the routeChangeErrors raised
   // by the resolve in config part of application
   $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){
       // I am redirecting to rootPath I have set above.
       $location.path($rootScope.rootPath);
   });
}]);

इस तरह हम कॉन्फ़िगर चरण के समय वादा विफलता को संभाल सकते हैं।


0

मेरे पास एक जटिल बहु-स्तरीय स्लाइडिंग पैनल इंटरफ़ेस है, जिसमें अक्षम स्क्रीन परत है। डिसेबल स्क्रीन लेयर पर निर्देश बनाना जो राज्य को निष्पादित करने के लिए क्लिक इवेंट बनाएगा

$state.go('account.stream.social.view');

एक चमक प्रभाव पैदा कर रहे थे। इसके बजाय history.back () ने ठीक काम किया, हालाँकि मेरे मामले में यह हमेशा इतिहास में वापस नहीं आया। तो मुझे जो पता चलता है वह यह है कि अगर मैं स्टेट के बजाय अपनी डिसेबल स्क्रीन पर केवल फीचर हाइपर बनाता हूं, तो एक आकर्षण की तरह काम किया है।

<a class="disable-screen" back></a>

निर्देशक 'बैक'

app.directive('back', [ '$rootScope', function($rootScope) {

    return {
        restrict : 'A',
        link : function(scope, element, attrs) {
            element.attr('href', $rootScope.previousState.replace(/\./gi, '/'));
        }
    };

} ]);

app.js मैं सिर्फ पिछली स्थिति को बचाता हूं

app.run(function($rootScope, $state) {      

    $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {         

        $rootScope.previousState = fromState.name;
        $rootScope.currentState = toState.name;


    });
});

-2

एक संभव समाधान उस तत्व के साथ एनजी-क्लोक निर्देश का उपयोग करना हो सकता है जहां हम मॉडल का उपयोग कर रहे हैं

<div ng-cloak="">
  Value in  myModel is: {{myModel}}
</div>

मुझे लगता है कि यह कम से कम प्रयास करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.