Actualización de URL en Angular JS sin volver a renderizar la vista

79

Estoy construyendo un sistema de tablero en AngularJS y tengo un problema al configurar la URL a través de $location.path

En nuestro tablero, tenemos un montón de widgets. Cada uno muestra una vista maximizada más grande cuando hace clic en él. Estamos intentando configurar enlaces profundos para permitir que los usuarios se vinculen a un panel con un widget maximizado.

Actualmente, tenemos 2 rutas que se parecen /dashboard/:dashboardIdy/dashboard/:dashboardId/:maximizedWidgetId

Cuando un usuario maximiza un widget, actualizamos la URL usando $location.path, pero esto hace que la vista se vuelva a renderizar. Como tenemos todos los datos, no queremos volver a cargar la vista completa, solo queremos actualizar la URL. ¿Hay alguna forma de establecer la URL sin hacer que la vista se vuelva a representar?

HTML5Modeestá configurado en true.

Ian Muir
fuente
1
Si desea que sus datos sobrevivan a los cambios de ruta en el lado del cliente, ¿por qué no enviarlos a un servicio?
Riko

Respuestas:

133

De hecho, se generará una vista cada vez que cambie una URL. Así es como funciona $ routeProvider en Angular, pero puede pasar maximizeWidgetIdcomo una cadena de consulta que no vuelve a representar una vista.

App.config(function($routeProvider) {
  $routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});

Cuando hace clic en un widget para maximizar:

<a href="#/dashboard/1?maximizeWidgetId=1">Maximum This Widget</a>
or
$location.search('maximizeWidgetId', 1);

La URL en la barra de direcciones cambiaría a http://app.com/dashboard/1?maximizeWidgetId=1

Incluso puede ver cuando la búsqueda cambia en la URL (de un widget a otro)

$scope.$on('$routeUpdate', function(scope, next, current) {
   // Minimize the current widget and maximize the new one
});
codef0rmer
fuente
1
Si se acepta la respuesta, crearé una pregunta separada sin ningún elemento ": param". Pregunta simplemente estúpida: cómo no volver a renderizar la vista.
OZ_
2
Creo que angular-ui-router será una opción obvia en ese caso.
codef0rmer
1
Estoy usando el $routeUpdateevento. Creo que $routeChangeStartse activa al mudarse a otra ubicación.
lucassp
@kuchumovn: Desafortunadamente, todavía estamos en 2014. Angular 2.0 tendrá un enrutamiento renovado (probablemente angular-ui-router incorporado) que haría lo que pretendías.
codef0rmer
1
@ codef0rmer, he encontrado esta respuesta más de una vez. ¡Gracias! ¡Gran respuesta, aún después de todo este tiempo!
helada
9

Puede establecer la propiedad reloadOnSearch de $ routeProvider en false.

Posible pregunta duplicada: ¿Puede cambiar una ruta sin recargar el controlador en AngularJS?

Saludos

bdavidxyz
fuente
Parece que es un duplicado. Desafortunadamente, parece que tienen el mismo problema, siempre que sea parte de la ruta de la URL, no una variable de consulta, se actualiza.
Ian Muir
No, no está duplicado.
OZ_
No es un duplicado, ya que la pregunta vinculada es sobre no recargar el controlador y se trata de no recargar la plantilla. La solución en la pregunta vinculada hará que la vista se recargue.
Lajos Meszaros
6

Para aquellos que necesitan cambiar la ruta completa () sin recargar los controladores

Aquí está el complemento: https://github.com/anglibs/angular-location-update

Uso:

$location.update_path('/notes/1');
Daniel Garmoshka
fuente
3
gracias, funciona. ¿Pero tal vez no deberías extender la $ location original?
rofrol
3

Estamos usando Angular UI Router en lugar de rutas integradas para un escenario similar. No parece volver a crear una instancia del controlador y volver a renderizar la vista completa.

DreamSonic
fuente
2
¿Ha intentado usar en $state.transitionTo()lugar de $location.path()?
DreamSonic
1
No cambio $ location.path () en absoluto, ¿dónde debería escribir $state.transitionTo()entonces?
OZ_
Cita: "Cuando un usuario maximiza un widget, actualizamos la URL usando location.path, pero esto hace que la vista se vuelva a renderizar". En lugar de cambiar la ruta, debe llamar, lo $state.transitionTo()que a su vez actualizará el hash de la URL.
DreamSonic
La idea es que debe tener dos estados anidados: uno para su tablero y otro para su widget maximizado. Cuando navega del estado principal al estado secundario, solo se volverá a representar la vista secundaria, no la vista principal.
DreamSonic
3

Me doy cuenta de que esta es una pregunta antigua, pero como me tomó un buen día y medio encontrar la respuesta, aquí va.

No necesita convertir su ruta en cadenas de consulta si usa angular-ui-router .

Actualmente, debido a lo que puede considerarse un error , establecer reloadOnSearch: falseun estado dará como resultado que se pueda cambiar la ruta sin volver a cargar la vista. El usuario de GitHub lmessinger incluso tuvo la amabilidad de proporcionar una demostración. Puede encontrar el enlace de su comentario vinculado arriba.

Básicamente, todo lo que necesitas hacer es:

  1. Usar en ui-routerlugar dengRoute
  2. En sus estados, declare los que desee con reloadOnSearch: false

En mi aplicación, tengo una vista de lista de categorías, desde la cual puede acceder a otra categoría usando un estado como este:

$stateProvider.state('articles.list', {
  url: '{categorySlug}',
    templateUrl: 'partials/article-list.html',
    controller: 'ArticleListCtrl',
    reloadOnSearch: false
  });

Eso es. ¡Espero que esto ayude!

ohanhi
fuente
2

Cómo lo he implementado:
(mi solución principalmente para casos en los que necesita cambiar la ruta completa, no las subpartes)

Tengo una página con menú (menuPage) y los datos no deben limpiarse en la navegación (hay muchas entradas en cada página y el usuario no estará muy contento si los datos desaparecen accidentalmente).

  1. desactivar $ routeProvider
  2. en el controlador mainPage, agregue dos divs con el atributo de directiva personalizada: cada directiva contiene solo 'templateUrl' y 'scope: true'

     <div ng-show="tab=='tab_name'" data-tab_name-page></div>
    
  3. El controlador mainPage contiene líneas para simular el enrutamiento:

    if (!$scope.tab && $location.path()) {
        $scope.tab = $location.path().substr(1);
    }
    $scope.setTab = function(tab) {
        $scope.tab = tab;
        $location.path('/'+tab);
    };
    

Eso es todo. Es un poco feo tener una directiva separada para cada página, pero el uso de templateUrl dinámico (como función) en la directiva provoca que se vuelva a renderizar la página (y se pierdan los datos de las entradas).

ONZ_
fuente
0

Si entendí bien tu pregunta, quieres,

  1. Maximice el widget cuando el usuario esté en / dashboard /: dashboardId y maximice el widget.
  2. Quiere que el usuario tenga la capacidad de volver a / dashboard /: dashboardId /: maximizedWidgetId y seguir viendo el widget maximizado.

Puede configurar solo la primera ruta en routerConfig y usar RouteParams para identificar si el widget maximizado se pasa en los parámetros en el controlador de esta ruta configurada y maximizar la pasada como parámetro. Si el usuario lo está maximizando la primera vez, comparta la URL de esta vista maximizada con maximizedWidgetId en la interfaz de usuario.

Siempre que use $ location (que es solo un contenedor sobre el objeto de ubicación nativo) para actualizar la ruta, actualizará la vista.

Sivakumar Kailasam
fuente
1
No solo $ location actualizará la vista. ng-include también lo hará, incluso sin cambiar $ location.
OZ_
@OZ_ No ​​sugerí ngInclude ya que esto es solo un cambio de estado dentro de una vista, simplemente estoy sugiriendo probablemente algo como ng-if que estaría asociado a una función que puede descubrir routeParams
Sivakumar Kailasam
0

Tengo una idea para usar

window.history.replaceState ('Objeto', 'Título', '/ nueva-url');

Si haces esto y ocurre un ciclo de digestión, arruinará completamente las cosas. Sin embargo, si lo vuelve a configurar en la URL correcta, angular espera que esté bien. Entonces, en teoría, podría almacenar la URL correcta que espera angular y restablecerla justo antes de que sepa que se activa un resumen.

Sin embargo, no lo he probado.

Keegan 82
fuente
-2

El siguiente código le permitirá cambiar la URL sin redirección, como: http: // localhost / # / 691? Foo? Bar? Blabla

for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});

Pero cuando cambie a http: // localhost / # / 692 , será redirigido.

a B C
fuente
No veo por qué agregar otra respuesta aquí.
gsamaras
1
es una nota a la historia.
abc