Titremeyi önlemek için model yüklenene kadar AngularJS yol değişikliğini erteleme


321

AngularJS için, her model ve verileri ilgili hizmetleri kullanılarak getirilene kadar yeni bir rota göstermeyi geciktirmenin bir yolu (Gmail'e benzer) olup olmadığını merak ediyorum .

Örneğin, ProjectsController tüm Projeleri listeleyen ve project_index.htmlbu Projeleri gösteren şablon olan bir tane Project.query()olsaydı, yeni sayfayı göstermeden önce tamamen getirilirdi.

O zamana kadar, eski sayfa gösterilmeye devam edecekti (örneğin, başka bir sayfaya göz atıyorsam ve sonra bu Proje dizinini görmeye karar verdiysem).

Yanıtlar:


374

$ routeProvider çözülmesine verileri yüklenene kadar özellik rota değişikliğinin geciktirmek sağlar.

Önce resolveböyle bir özelliğe sahip bir rota tanımlayın .

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özelliğin rotada tanımlandığına dikkat edin .

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;
  }
}

Denetleyici tanımının, denetleyici yapıcısı tarafından kullanılabilir olması gereken şeyleri bildiren bir çözüm nesnesi içerdiğine dikkat edin. Burada phonesdenetleyiciye enjekte edilir ve resolveözellikte tanımlanır .

resolve.phonesFonksiyon bir söz dönen sorumludur. Tüm vaatler toplanır ve tüm vaatler çözülene kadar rota değişikliği ertelenir.

Çalışma demosu: http://mhevery.github.com/angular-phonecat/app/#/phones Kaynak: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831


10
@MiskoHevery - denetleyicileriniz bir modülün içindeyse ve işlev yerine dize olarak tanımlanırsa. Çözüm özniteliğini sizin gibi nasıl kurabilirsiniz?
aar0n

53
Bu, angular.controller()tip kontrolörü tanımlarında nasıl kullanılır ? İçinde, $routeProviderdenetleyicilerin dize adlarını kullanmanız gerektiğini düşündüm.
Ben Lesh

6
Angular.controller () kullanarak ve AngularJS'nin en son sürümüne sahip herhangi bir örnek?
Laurent

22
@blesh, kullandığınızda angular.controller(), bu işlevin sonucunu bir değişkene ( var MyCtrl = angular.controller(...)) atayabilir ve daha sonra bununla ( MyCtrl.loadData = function(){..}) daha fazla çalışabilirsiniz . Egghead'in
petrkotek

17
Denetleyicinizi küresel bir yere yerleştirmeden yapmak için hala güzel bir yol istiyorum. Ben her yerde küresel ile çöp istemiyorum. Bunu bir sabitle yapabilirsiniz, ancak çözme işlevini başka bir yere değil, denetleyiciye / denetleyiciye yerleştirebilmeniz iyi olur.
Erik Honn

51

İşte Açısal 1.0.2 için çalışan minimal bir çalışma örneği

Şablon:

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

<div ng-view>

</div>

JavaScript:

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/

Kolaylaştırılmış sürüm:

$ Http () zaten bir söz verdi (ertelenmiş), aslında kendimizi yaratmamız gerekmiyor. Böylece MyCtrl'i basitleştirebiliriz. çözüm:

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

$ Http () sonucu veri , durum , üstbilgiler ve yapılandırma nesneleri içerir, bu nedenle MyCtrl gövdesini şu şekilde değiştirmemiz gerekir:

$scope.datasets = datasets.data;

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


Ben böyle bir şey yapmaya çalışıyorum ama tanımlanmadığı gibi 'veri kümeleri' enjekte etmekte sorun yaşıyorum. Düşüncesi olan var mı?
Rob Bygrave

Hey mb21, sanırım bu soruda bana yardımcı olabilirsiniz: stackoverflow.com/questions/14271713/…
winduptoy

Birisi bu yanıtı app.controller ('MyCtrl') biçimine dönüştürmeme yardımcı olabilir mi? jsfiddle.net/5usya/1 benim için çalışmadı.
user1071182

bir hata alıyorum:Unknown provider: datasetsProvider <- datasets
chovy

Veri setlerini bununla değiştirerek cevabınızı basitleştirebilirsiniz:function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
Morteza Tourani

32

Bazı insanlar bunu minimal dostu bağımlılık enjeksiyonu ile angular.controller yöntemini kullanarak nasıl yapılacağını sordum. Bu işe yeni başladığımdan beri geri dönüp yardım etmek zorunda kaldım. İşte benim çözümüm (orijinal sorudan ve Misko'nun cevabından benimsenmiştir):

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';
}]);

Bu kod sorudan / en popüler cevaptan türetildiğinden, test edilmemiştir, ancak minyatür dostu açısal kodun nasıl yapıldığını zaten biliyorsanız, doğru yönde göndermeniz gerekir. Kendi kodumun gerektirmediği bir parça, 'telefonlar' için çözümleme işlevine bir "Telefon" enjeksiyonu oldu, ne de herhangi bir 'gecikme' nesnesi kullanmadım.

Bu youtube videosunu da http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , bana biraz yardımcı oldu

İlginizi çekerse, kendi kodumu da yapıştırmaya karar verdim (coffeescript'te yazıldı), böylece nasıl çalıştığımı görebilirsiniz.

FYI, önceden çeşitli modellerde CRUD yapmama yardımcı olan genel bir kontrolör kullanıyorum:

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 ....
    ]

Örneğinizden doğru bir şekilde çıkarımda mıyım ve başarısız girişimlerim artık Angular'ın resolveson sürümlerinde denetleyicideki bir işleve başvurmanın imkansız olduğunu düşünüyor mu? Yani burada olduğu gibi yapılandırmada ilan edilmelidir?
XML

@XMLilley Durumun bundan eminim. Bu örnek, yazarken 1.1.2'den geldi, inanıyorum. Bir denetleyicinin içine çözüm koyarak herhangi bir belge görmedim
bitwit

2
Harika, teşekkürler. SO'da bunu yapmak için birçok örnek var (buradaki ilk ikisi gibi), ancak hepsi 2012'den ve 2013'ün başlarından. Bu zarif bir yaklaşım, ancak kullanımdan kaldırılıyor gibi görünüyor. En temiz alternatif, söz verilen nesneler olan bireysel hizmetler yazmak gibi görünüyor.
XML

Teşekkürler bu benim için çalıştı. Tanımsız $deferhizmet hakkında hata alan herkes için , AngularJS'nin 1.5.7 sürümünde $timeoutbunun yerine kullanmak istediğinizi unutmayın .
racl101

18

1.1.5 ve daha sonraki sürümlerin bir parçası olan bu taahhüt , $promisenesnesini ortaya koyar $resource. Bu taahhüdü içeren ngResource sürümleri, aşağıdaki gibi kaynakların çözümüne izin verir:

$ routeProvider

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

kontrolör

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

    $scope.data = data;

}]);

Hangi sürümler bu taahhüdü içerir?
XML

En son kararsız sürüm (1.1.5) bu taahhüdü içerir. ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js
Maximilian Hoffmann

Bu daha az ayrıntılı yaklaşımı seviyorum. Gerçek veri nesnesinden bir söz oluşturmak ve doğrudan geçmek güzel olurdu, ama bu çok az kod güzel çalışır.
Sam Barnum

1
Kaynak $ routeParams'a nasıl erişir? Örneğin: in GET '/api/1/apps/:appId'-> App.get({id: $routeParams.appId}).$promise();Böyle kullanamam
zeronone

2
@zeronone $routesizin çözüm ve kullanım enjekte $route.current.params. Dikkatli olun, $routeParamshala eski rotayı işaret ediyor.
Brice Stacey

16

Bu snippet bağımlılık enjeksiyon dostudur ( ngmin ve uglify kombinasyonunda bile kullanıyorum ) ve daha zarif bir alan güdümlü tabanlı çözüm.

Aşağıdaki örnek, bir Telefon kaynağını ve söz konusu (telefon) etki alanı için tüm yönlendirme bilgilerinizi içeren sabit bir phoneRoutes kaydeder . Sağlanan cevapta beğenmediğim bir şey, çözüm mantığının konumuydu - ana modül, hiçbir şey bilmemeli veya kaynak argümanlarının denetleyiciye sağlanma şekli hakkında rahatsız olmamalıdır . Bu şekilde mantık aynı alanda kalır.

Not: ngmin kullanıyorsanız (ve eğer değilseniz: yapmanız gerekir), sadece DI dizi kuralıyla çözüm fonksiyonlarını yazmanız gerekir.

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;
        }]
      }
    }
  });

Bir sonraki parça, modül yapılandırma durumundayken yönlendirme verilerini enjekte eder ve $ routeProvider öğesine uygular .

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: '/' });

});

Bu yapılandırmayla rota yapılandırmasını test etmek de oldukça kolaydır:

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);
      });
    });
  });
});

En son (gelecek) denememde tam bir ihtişamla görebilirsiniz . Bu yöntem benim için iyi çalışıyor olsa da, gerçekten neden bir enjektör vaat nesnesi olan bir şey enjeksiyon algıladığında bir şey yapımını geciktirmiyor merak ediyorum ; soooOOOOOooOOOOO şeyleri çok daha kolay hale getirir.

Düzenle: ikinci el Angular v1.2 (rc2)


2
Bu mükemmel cevap "Açısal" felsefesi (kapsülleme vb.) İle çok daha uyumlu görünmektedir. Hepimiz mantığın kudzu gibi tüm kod tabanının üzerinde sürünmesini durdurmak için bilinçli bir çaba harcamalıyız.
zakdances

I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise objectBu işlevselliği atladıklarını tahmin ediyorum çünkü uygulamaların duyarlılığını olumsuz yönde etkileyen tasarım modellerini teşvik edebilir. Zihnindeki ideal uygulama gerçekten eşzamansız olanıdır, bu yüzden çözümleme bir son durum olmalıdır.
zakdances

11

Rotayı göstermeyi geciktirmek, eşzamansız bir karışıklığa yol açacağından emin olabilirsiniz ... neden ana varlığınızın yükleme durumunu izlemiyor ve bunu görünümde kullanmıyorsunuz. Örneğin oyun kumandanızda ngResource'taki hem başarı hem de hata geri çağrılarını kullanabilirsiniz:

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

Sonra görünümde her şeyi yapabilirsiniz:

<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
Belki de HTTP durumunu görünüme maruz bırakmak doğru değildir, artık CSS sınıfları ve denetleyiciye ait DOM öğeleri ile uğraşmaktan daha doğrudur. Muhtemelen aynı fikri kullanırdım ama soyut durumu uzakta isValid () ve isLoaded ().
jpsimons

1
Bu gerçekten endişelerin en iyi ayrımı değil, ayrıca belirli bir nesneye bağlı iç içe denetleyicileriniz varsa çökecektir.
null

Bu oldukça zekidir .. durum kodlarını görünüme maruz bırakmak için, sadece http mantığı denetleyicinin kapsam özelliklerine yapıştırabilir, sonra onlara bağlayabilirsiniz. Ayrıca, arka planda gerçekleşen birden fazla ajax çağrısı yapıyorsanız, bunu yine de yapmak istersiniz.
KingOfHococrites

Eğer sorun sadece bir görüşü erteleme meselesi olsaydı bu iyi olurdu. Ancak, yalnızca görünüm değil, bir denetleyicinin örneğini geciktirmeniz gerekiyorsa, çözüm en iyi şekilde kullanılır . (Örn: JSON'unuzun yüklendiğinden emin olmanız gerekiyorsa, denetleyiciniz kablolamadan önce bir yönerge iletir.) Dokümanlardan: "yönlendirici , denetleyicinin çözülmeden önce hepsinin çözülmesini veya reddedilmesini bekler somutlaştırılmış ".
Dan

8

Yukarıdaki Misko'nun kodundan çalıştım ve bununla yaptım. Bu, daha güncel bir çözüm $deferolarak değiştirildi $timeout. $timeoutAncak, değiştirme işlemi, zaman aşımı süresini (Misko kodunda 1 saniye) bekleyecek ve daha sonra zaman içinde çözüleceğini umarak verileri döndürecektir. Bu şekilde, en kısa sürede geri döner.

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 Kullanımı

AngularJS 1.1.5 sözdizimini kullanarak Justen'in cevabındaki 'telefonlar' işlevini güncelleme .

Orijinal:

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

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

    return deferred.promise;
}

Güncellenmiş:

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

Açısal ekip ve katkıda bulunanlar sayesinde çok daha kısa. :)

Bu aynı zamanda Maximilian Hoffmann'ın da cevabı. Görünüşe göre bu taahhüt onu 1.1.5'e dönüştürdü.


1
Ben hakkında bir şey bulmak için görünmüyor olabilir $promisede docs . V2.0 + 'dan çıkarılmış olabilir.
zakdances

Sadece 1.2
Thomas

5

Veriler yüklenene kadar rota değişikliğini geciktirmek için $ routeProvider solve özelliğini kullanabilirsiniz.

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Özelliğin rotada tanımlandığına dikkat edin .

EntitiesCtrlResolveve EntityCtrlResolvebir sabit aynı dosyada belirlenen amaçları EntitiesCtrlve EntityCtrlkontrol.

// 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

Darkporter'ın fikrini seviyorum çünkü AngularJS için yeni bir geliştirme ekibinin anlaması ve hemen çalışması kolay olacak.

Biri yükleyici çubuğu için diğeri veri yüklendikten sonra görüntülenen gerçek içerik için 2 div kullanan bu uyarlamayı oluşturdum. Hata yönetimi başka bir yerde yapılır.

$ Scope 'hazır' bayrağı ekleyin:

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

HTML görünümünde:

<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>

Ayrıca bakınız: Boostrap ilerleme çubuğu belgeleri


Birden fazla veri parçası yüklüyorsanız biraz parçalanır. Her şeyin yüklü olup olmadığını nasıl anlarsınız?
toxaq

Bu yanıtı Şubat ayında eklediğimden beri, bu sayfada çok daha fazla etkinlikle işler devam etti. Angular'da bu sorunu çözmek için burada önerilenden daha iyi bir destek var gibi görünüyor. Şerefe,
reggoodwin

Biraz geç geliyorum, ancak birden fazla veri parçasıyla uğraşmak büyük bir endişe değil. Her istek için ayrı değişkenler (booleans: isReadyData1, isReadyData2 vb.) Kullanmanız ve $ scope.ready = isReadyData1 && isReadyData2 ... ayarlamanız gerekir; benim için iyi çalışıyor.
GuillaumeA

1

Yukarıdaki cevapları beğendim ve onlardan çok şey öğrendim ama yukarıdaki cevapların çoğunda eksik olan bir şey var.

Sunucudan ilk istekte getirilen bazı verilerle url çözüyordum benzer bir senaryoda sıkışmıştı. Karşılaştığım sorun, vaat olsaydı rejected.

Ben dönmek için kullanılan özel bir sağlayıcı kullanıyordum Promisetarafından çözüldü hangi resolvebir $routeProvideryapılandırma aşamasının anda.

Burada vurgulamak istediğim şey, when bunun böyle bir şey yaptığı .

URL'yi url çubuğunda görür ve daha sonra whendenilen denetleyici ve görünümdeki ilgili blok şimdiye kadar iyi şekilde adlandırılır.

Diyelim ki aşağıdaki yapılandırma faz koduna sahibim.

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

Tarayıcıdaki kök url'de çalıştırmanın ilk bloğu başka türlü otherwiseçağrılır.

Adres çubuğu AuthServicePrivider.auth()işlevinde rootUrl tuşuna bastığım bir senaryo çağrıldığını düşünelim .

Diyelim ki geri dönen Promise ne durumda ret durumunda ?

Hiçbir şey işlenmez.

Otherwise block, config bloğunda tanımlı olmayan ve angularJs config fazında bilinmeyen herhangi bir url için olduğu gibi yürütülmez.

Bu söz çözülmediğinde işten çıkarılan olayı ele almamız gerekecek. Başarısızlık $routeChangeErorrüzerine ateş alır$rootScope .

Aşağıdaki kodda gösterildiği gibi yakalanabilir.

$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 Etkinlik izleme kodunu uygulama çalıştırma bloğuna koymak genellikle iyi bir fikirdir. Bu kod, uygulamanın yapılandırma aşamasından hemen sonra çalışır.

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);
   });
}]);

Bu şekilde yapılandırma aşaması sırasında vaat hatası ile başa çıkabiliriz.


0

Ekran katmanı devre dışı, karmaşık bir çok seviyeli sürgülü panel arayüzü vardı. Durumu devre dışı bırakmak için click olayı oluşturacak olan devre dışı bırakma ekran katmanında yönerge oluşturma

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

bir titreşim etkisi üretiyordu. Bunun yerine history.back () işe yaradı, ancak benim durumumda her zaman geri değil. Öyleyse ne bulmak sadece state.go yerine devre dışı benim ekranda öznitelik href oluşturmak, bir cazibe gibi çalıştı olmasıdır.

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

'Geri' direktifi

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

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

} ]);

app.js Sadece önceki durumu kaydediyorum

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

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

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


    });
});

-2

Olası bir çözüm, modelleri kullandığımız elemanla ng-cloak yönergesini kullanmak olabilir.

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

Bunun en az çaba gerektirdiğini düşünüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.