Cambio de vistas en tiempo de ejecución con AngularJS

1
14003

En este tutorial se ve cómo cambiar programáticamente en tiempo de ejecución vistas parciales de aplicaciones web con AngularJS.

AngularJS permite de forma sencilla construir una SinglePageApplication con un index y varias vistas que suelen cambiar en función de una ruta que se emula para permitir una “navegación”.

Lo que no es tan intuitivo es cómo conseguir que una de estas vistas cambie a voluntad en función de eventos que ocurran sin que cambie la ruta de la página.

Voy a mostraros una forma de conseguir esto. Pueden existir otras formas de lograrlo, pero al igual que las definiciones de un patrón de diseño, esta es una solución probada a un problema conocido.

Nuestro objetivo es que la vista de detalle (la rosa) y su controlador asociado cambien en función de qué botón pulsemos.

Nuestro index.html tiene inicialmente esta forma.

index.html

<div class="main" ng-controller="mainController as mainCtrl" ng-init="mainCtrl.init()">

     <div class="panel-cabecera"  ng-include="'html/app/header.html'" ng-controller="headerController as headerCtrl"></div>

      <div class="panel-izquierda"  ng-include="'html/app/flujo.html'" ng-controller="flujoController as flujoController"></div>

<!-- aquí va el ng-include que debe ser dinámico para el detalle -->
 
</div>

Un controlador padre llamado mainController con la funcionalidad común entre los hijos, y una vista con controlador por cada parte de la pantalla.

Para agregar la vista dinámica para el detalle de los procesos del flujo vamos a introducir el nombre del fichero html en una variable en el controlador principal mainController.

<div class="panel-derecha" ng-include="mainController.tpl.contentUrl"></div>

Quedando nuestro index.html de esta forma.

index.html

<div class="main" ng-controller="mainController as mainCtrl" ng-init="mainCtrl.init()">

     <div class="panel-cabecera"  ng-include="'html/app/header.html'" ng-controller="headerController as headerCtrl"></div>

      <div class="panel-izquierda"  ng-include="'html/app/flujo.html'" ng-controller="flujoController as flujoController"></div>

      <div  class="panel-derecha" ng-include="mainController.contentUrl"></div>
 
</div>


En nuestro controlador main tenemos declarada nuestra variable y una función para cambiarla

mainController.js
//mainController
var vm = this;
vm.contentUrl = 'html/app/compra.html';

vm.changeStep = function (step) {
    vm.contentUrl = 'html/app/' + step + '.html';
}

Por si os resulta extraño el uso de vm, es una convención que se sigue, y su funcionamiento es análogo a usar $scope.

Ahora dentro del html de la vista de la izquierda del control de flujo, introducimos llamadas al mainController para llamar a nuestra función en cada uno de los links mediante el uso de ng-click.

ng-click="mainCtrl.changeStep('compra')

ng-click="mainCtrl.changeStep('modoPago')

ng-click="mainCtrl.changeStep('realizarPago')

Y al clicar en cada boton, nuestra vista de detalle cambiará a la que necesitemos.

Por último, necesitamos un controlador para cada vista específica, en mis pruebas estuve buscando un modo para introducir un controlador dinámico en el ng-include, pero al final he optado por usar el pensamiento lateral en busca de una solución más sencilla, y la forma más cómoda es introducir cada controlador dentro del primer elemento de la plantilla concreta de detalle, ya que este va a ser fijo.

<div class="detalle-compra" ng-controller="detalleCompraController as detalleCtrl">
    …
</div>

Espero que os haya resultado útil y si alguna vez tenéis un problema similar, os ayude a tener algo con lo que empezar.

Un saludo,

Samuel Martín Gómez-Calcerrada

1 COMENTARIO

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad