9

Chcę przechwycić wszystkie zmiany trasy z Sammy, aby najpierw sprawdzić, czy jest oczekująca akcja. Zrobiłem to za pomocą interfejsu API sammy.before i zwracam wartość false, aby anulować trasę. Dzięki temu użytkownik pozostaje na "stronie", ale nadal zmienia hasz w pasku adresu przeglądarki i dodaje trasę do historii przeglądarek. Jeśli anuluję trasę, nie chcę jej w pasku adresu ani w historii, ale zamiast tego oczekuję, że adres pozostanie taki sam.Anuluj trasę za pomocą Sammy.js bez wpływu na historię

Obecnie, aby obejść ten problem, mogę wywołać window.history.back (yuk), aby wrócić do pierwotnego miejsca w historii lub sammy.redirect. Oba są mniej niż idealne.

Czy istnieje sposób, aby sammy naprawdę anulować trasę, tak aby pozostała na aktualnej trasie/stronie, pozostawia pasek adresu, jak jest, i nie dodaje do historii?

Jeśli nie, czy jest inna biblioteka routingu, która to zrobi?

sammy.before(/.*/, function() { 
    // Can cancel the route if this returns false 
    var response = routeMediator.canLeave(); 

if (!isRedirecting && !response.val) { 
    isRedirecting = true; 
    // Keep hash url the same in address bar 
    window.history.back(); 
    //this.redirect('#/SpecificPreviousPage'); 
} 
else { 
    isRedirecting = false; 
} 
return response.val; 
}); 

Odpowiedz

17

W przypadku, gdy ktoś inny trafi to, tutaj jest miejsce, w którym skończyłem. Postanowiłem użyć funkcji sammy dla context.setLocation do obsługi resetowania trasy.

sammy.before(/.*/, function() { 
    // Can cancel the route if this returns false 
    var 
     context = this, 
     response = routeMediator.canLeave(); 

    if (!isRedirecting && !response.val) { 
     isRedirecting = true; 
     toastr.warning(response.message); // toastr displays the message 
     // Keep hash url the same in address bar 
     context.app.setLocation(currentHash); 
    } 
    else { 
     isRedirecting = false; 
     currentHash = context.app.getLocation(); 
    } 
    return response.val; 
}); 
+0

Hahaha John, mam tutaj szukając więcej informacji o tym, jak to osiągnąć w serii SPA :-) –

1

Przy użyciu kodu podanego w pytaniu i odpowiedzi trzeba zauważyć, że trasa, którą anulowane zostaną także zablokowane dla wszystkich przyszłych połączeń, routeMediator.canLeave nie zostaną ponownie ocenione. Wywołanie trasy dwukrotnie i anulowanie jej w zależności od bieżącego stanu nie jest możliwe.

+1

Hmmm. Ciekawi mnie, dlaczego tak mówisz. Użyłem tego kodu i nie blokuję przyszłych połączeń z canLeave. Czy możesz rozwinąć? Jeśli mam błąd, chciałbym zrozumieć, jak to naprawić. –

+0

Dokumentacja Sammy dla wcześniej mówi: "Jeśli którykolwiek z callbacków wyraźnie zwróci fałsz, wykonanie jakichkolwiek dalszych wywołań zwrotnych i sama trasa zostanie zatrzymana." - to właśnie zaobserwowałem z powyższym kodem. Dzieje się tak tylko przy dwukrotnym dostępie do zablokowanej trasy. Podczas uzyskiwania dostępu do innej trasy między wszystkim działa dobrze. –

+2

Trasa jest zatrzymana, tak. Ale nie oznacza to, że przyszłe połączenia z trasą są blokowane. Nie widzę takiego zachowania, mogę powstrzymać to od odejścia, a potem nadal będzie to wołało następnym razem. –

0

Mogłem wyprodukować takie same wyniki, jak zrobił to John Papa, gdy używał SammyJS na kursie SPA/Knockout.

Użyłem Crossroads JS jako routera, który polega na Hasher JS, aby słuchać zmian URL "emitowanych" przez przeglądarkę.

próbki kodu jest:

hasher.changed.add(function(hash, oldHash) { 
    if (pageViewModel.isDirty()){ 
     console.log('trying to leave from ' + oldHash + ' to ' + hash); 

     hasher.changed.active = false; 
     hasher.setHash(oldHash); 
     hasher.changed.active = true; 

     alert('cannot leave. dirty.'); 
    } 
    else { 
     crossroads.parse(hash); 
     console.log('hash changed from ' + oldHash + ' to ' + hash); 
     } 
}); 
0

Po revisiting starszą projekt i mający podobną sytuację, chciałem podzielić się innego podejścia, tak na wszelki wypadek, gdyby ktoś inny jest skierowana tutaj.

Potrzebny był zasadniczo nowoczesny wzorzec "auth guard" do przechwytywania stron i przekierowania na podstawie poświadczeń.

Co działa dobrze używał Sammy.around(callback) jak zdefiniowano tutaj: Sammy.js docs: Sammy.Application around(callback)

Następnie, po prostu wykonaj następujące czynności ...

(function ($) { 
    var app = Sammy("body"); 

    app.around(checkLoggedIn); 

    function canAccess(hash) { 
     /* access logic goes here */ 
     return true; 
    } 

    // Authentication Guard 
    function authGuard(callback) { 
     var context = this; 
     var currentHash = app.getLocation(); 
     if (!canAccess(currentHash)) { 
      // redirect 
      context.redirect("#/login"); 
     } 
     else { 
      // execute the route path 
      callback(); 
     } 
    }; 

})(jQuery);