9

Quiero interceptar todos los cambios de ruta con Sammy para verificar primero si hay una acción pendiente. Lo he hecho usando la API sammy.before y devuelvo falso para cancelar la ruta. Esto mantiene al usuario en la 'página', pero aún cambia el hash en la barra de direcciones de los navegadores y agrega la ruta al historial de los navegadores. Si cancelo la ruta, no la quiero en la barra de direcciones ni en el historial, pero espero que la dirección no cambie.Cancelar ruta usando Sammy.js sin afectar el historial

Actualmente, para evitar esto puedo llamar a window.history.back (yuk) para volver al punto original en el historial o sammy.redirect. Ambos son menos que ideales.

¿Hay alguna manera de hacer que Sammy realmente cancele la ruta para que permanezca en la ruta/página actual, abandone la barra de direcciones como está y no se agregue al historial?

Si no, ¿hay otra biblioteca de enrutamiento que hará esto?

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

Respuesta

17

En caso de que alguien más golpee esto, aquí es donde terminé. Decidí usar la función context.setLocation de sammy para manejar el restablecimiento de la ruta.

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

Jajaja Juan, llegué aquí buscando más información acerca de cómo se logró este en su serie SPA :-) –

1

Cuando se utiliza el código proporcionado dentro de la pregunta y la respuesta que tiene que darse cuenta de que la ruta ha cancelado también será bloqueada para todas las llamadas futuras, routeMediator.canLeave no será evaluado de nuevo. Llamar a una ruta dos veces y cancelarla según el estado actual no es posible con esto.

+1

Hmmm. Tengo curiosidad por qué dices eso. He usado este código y no está bloqueando futuras llamadas a canLeave. ¿Puedes elaborar? Si tengo un error, me gustaría saber cómo solucionarlo. –

+0

La documentación de Sammy para antes dice: "Si cualquiera de las devoluciones de llamada explícitamente devuelve falso, la ejecución de cualquier devolución de llamada adicional y la ruta en sí se detiene". - Esto es lo que observé con el código de arriba. Esto solo ocurre cuando se accede a la ruta bloqueada consecutivamente dos veces. Al acceder a otra ruta entre todo funciona bien. –

+2

La ruta está detenida, sí. Pero no dice que se previenen futuras llamadas a la ruta. No veo este comportamiento, puedo evitar que se vaya, y luego todavía lo llama la próxima vez. –

0

Podría producir los mismos resultados que John Papa cuando utilizó SammyJS en el curso SPA/Knockout.

Utilicé Crossroads JS como enrutador, que depende de Hasher JS para escuchar los cambios de URL "emitidos" por el navegador.

Ejemplo de código es:

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

Después de volver a visitar un proyecto de edad avanzada y tener una situación similar, que quería compartir otro enfoque, por si acaso alguien se dirige aquí.

Lo que se necesitaba era esencialmente un moderno patrón de "protección de autenticación" para interceptar páginas y redireccionar en función de las credenciales.

¿Qué funcionó bien utilizaba Sammy.around(callback) como se define aquí: Sammy.js docs: Sammy.Application around(callback)

A continuación, sólo tiene que hacer lo siguiente ...

(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); 
Cuestiones relacionadas