Estoy creando una interfaz de usuario simple usando Angular Meteor 2.
1) Tengo un componente de la barra de navegación superior que tiene un botón de "cerrar sesión".
2) Al hacer clic en el botón "cerrar sesión", se redirige a "iniciar sesión".
3) Entonces veo este error en la consola:EXCEPTION: Attempt to use a destroyed view: detectChanges
Excepción:
EXCEPTION: Attempt to use a destroyed view: detectChanges
browser_adapter.js:77 EXCEPTION: Attempt to use a destroyed view: detectChangesBrowserDomAdapter.logError @ browser_adapter.js:77BrowserDomAdapter.logGroup @ browser_adapter.js:87ExceptionHandler.call @ exception_handler.js:57(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
browser_adapter.js:77 STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:59(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
browser_adapter.js:77 Error: Attempt to use a destroyed view: detectChanges
at ViewDestroyedException.BaseException [as constructor] (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:3349:23)
at new ViewDestroyedException (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:10626:16)
at DebugAppView.AppView.throwDestroyedError (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11277:72)
at DebugAppView.AppView.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11230:18)
at DebugAppView.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11321:44)
at ViewRef_.detectChanges (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11011:65)
at http://localhost:3000/app/app.js?hash=323b1216814e80ed467d95bcda255eb217d7c468:2224:23
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:72)
------------- Elapsed: 80 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMacroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4652:47)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4467:37
at setTimeout (eval at createNamedFn (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5346:24), <anonymous>:3:37)
at new TopNavbarComponent (http://localhost:3000/app/app.js?hash=323b1216814e80ed467d95bcda255eb217d7c468:2221:9)
at DebugAppView._View_HomeComponent0.createInternal (HomeComponent.template.js:48:34)
at DebugAppView.AppView.create (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:11098:21)
------------- Elapsed: 2 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4930:25
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at ZoneAwarePromise.then (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5011:25)
at RuntimeCompiler.resolveComponent (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:40230:14)
at DynamicComponentLoader_.loadNextToLocation (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:10788:31)
at RouterOutlet.activate (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:26844:26)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
at Object.onInvoke (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9402:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
at Object.onInvoke (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9402:41)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4930:25
at ZoneDelegate.invokeTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4721:174)
at Object.onInvokeTask (http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:9393:41)
------------- Elapsed: 1 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at ZoneAwarePromise.then (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5011:25)
at http://localhost:3000/packages/modules.js?hash=560db94ec01c0b3e8f499491ffcce7a2ec6c3c5e:26895:53
at http://localhost:3000/packages/meteor.js?hash=ae8b8affa9680bf9720bd8f7fa112f13a62f71c3:1105:22
at ZoneDelegate.invoke (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4696:161)
------------- Elapsed: 0 ms; At: Wed Jun 15 2016 20:22:09 GMT-0700 (PDT) -------------
at Object.onScheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:5734:30)
at ZoneDelegate.scheduleTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4704:57)
at Zone.scheduleMicroTask (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4649:47)
at scheduleResolveOrReject (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4928:22)
at resolvePromise (http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4893:29)
at http://localhost:3000/packages/barbatus_angular2-runtime.js?hash=fda9b73362c52e988ad030102a9f58e4d584cda3:4877:21
at http://localhost:3000/packages/meteor.js?hash=ae8b8affa9680bf9720bd8f7fa112f13a62f71c3:1105:22BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:60(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runTask @ angular2-polyfills.js:323ZoneTask.invoke @ angular2-polyfills.js:490
Subscriber.js:229 Uncaught Attempt to use a destroyed view: detectChanges
top-navbar.component.ts
"use strict";
import {Logger} from "../services/logger.service";
import {Component, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core';
import {User} from "../models/user";
import {Router} from '@angular/router-deprecated';
import {UserService} from "../services/user.service";
import {CORE_DIRECTIVES} from '@angular/common';
import {DROPDOWN_DIRECTIVES} from '../../node_modules/ng2-bootstrap';
@Component({
selector: 'top-navbar',
templateUrl: 'client/top-navbar/top-navbar.html',
bindings: [UserService, Logger],
directives: [CORE_DIRECTIVES, DROPDOWN_DIRECTIVES]
})
export class TopNavbarComponent {
public user:User;
public statusDropdown = {
isOpen: false
};
constructor(private userService:UserService, private router:Router, private logger:Logger, private ref:ChangeDetectorRef) {
setTimeout(() => {
this.ref.markForCheck();
this.user = this.userService.getLoggedInUser();
this.ref.detectChanges();
}, 0)
}
logout() {
this.logger.warn('[Top Navbar] Logging out the user.');
localStorage.clear();
this.router.navigateByUrl('/login');
}
}
y este es mi login.component.ts
"use strict";
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormBuilder, ControlGroup, Validators } from '@angular/common';
import { MeteorComponent } from 'angular2-meteor';
import { Router } from '@angular/router-deprecated';
import { Logger } from "../services/logger.service";
@Component({
selector: 'login',
templateUrl: 'client/login/login.html',
changeDetection: ChangeDetectionStrategy.OnPush,
bindings: [Logger]
})
export class LoginComponent extends MeteorComponent {
loginForm:ControlGroup;
loginFailed = false;
constructor(private _logger:Logger, private _router:Router, private ref:ChangeDetectorRef) {
super();
let fb = new FormBuilder();
this.loginForm = fb.group({
username: ["", Validators.required],
password: ["", Validators.required]
});
}
login() {
this.call('authenticateUser', this.loginForm.value.username, this.loginForm.value.password, (err, data) => {
if (err) {
this._logger.error(err);
} else {
this._logger.info('[Authentication API] ', data);
if (data.status != 'LOGIN_SUCCESS') {
this.loginFailed = true;
} else {
this.loginFailed = false ;
var user = {
id: data.id,
name: data.name,
role: data.role
}
localStorage.setItem('user', JSON.stringify(user));
this._router.navigate(['Home'])
}
//This is required for letting Angular know that something has changed.
//Because this part of code runs out of Angular zone.
this.ref.markForCheck(); // Mark this component and its children for change detection in next detecting cycle.
this.ref.detectChanges(); // Trigger change detection.
}
});
}
}
angular
angular2-meteor
Abhishek
fuente
fuente
Respuestas:
La única solución que funcionó para mí fue:
fuente
isDestroyed
en cada componente donde se necesitaba (es decir, donde cancelar la suscripción no era suficiente). Configuré el campo en verdadero en ngOnDestroy y lo usé en lugar de intentar acceder al campo interno del detector de cambios ref.detach
lacdr
del componente que ya no se rindió.destroyed
no es parte de la API pública delchangeDetectionRef
objeto. ¿Hay alguna forma de aplicar esto sin acceder a él['destroyed']
?!(this.changeDetectionRef as ViewRef).destroyed
para hacerlo un poco menos hacky, pero sigue siendo bastante hacky en estos díasResolví el mismo problema tuyo, pero con un código mucho más pequeño, te diré el punto que podría ayudarte a resolver el problema.
El problema proviene claramente de
detectChanges()
que se realizaron los cambios y se llamó al método durante la fase de destrucción del componente.Por lo tanto, debe hacer que su componente sea
implements OnDestroy
, luego debe cancelar los cambios que hacenthis.ref.detectChanges()
para ser llamado. por lo queTopNavbarComponent
debe ser similar a:PD: ¡No olvide a
unsubscribe()
todos los observadores que tiene en su componente! De todos modos, tiene que hacer eso, las suscripciones sin darse de baja podrían ser la razón principal de cientos de problemas, incluido este, consulte Angular / RxJs ¿Cuándo debo cancelar la suscripción de `Suscripción`Editar : conozco otra solución en la web que intenta resolver el problema manejando el error en sí, mientras que la mejor práctica es conocer la raíz del problema, verificar si la vista destruida o no es una buena solución, pero la causa original podría ser un problema detrás de la fuga de memoria, por lo que la raíz del problema es que se debe eliminar el servicio en ejecución, NO solo intentar eliminar el error sin la raíz, por ejemplo, las suscripciones en ejecución (especialmente la personalizada) deben estar cerradas.
ASÍ que las tareas de limpieza son necesarias para un mejor rendimiento, no siempre es una solución más fácil y rápida, es mejor, si escondes la suciedad debajo de las alfombras no significa que limpiaste tu habitación :)
fuente
ChangeDetectorRef
nombre de su servicio es incorrecto, tal vez? si lo tieneprivate cdRef: ChangeDetectorRef
en el constructor debería estar funcionando.detectChanges
) durante la fase de destrucción?detectChanges
y se produjeron cambios durante la fase de destrucción, esta función comenzará a aplicar cambios en el componente muerto antes de que los servicios mueran también, por lo que el problema ocurrirá, es algo relacionado con Ver el ciclo de vida de angular, de todos modos puede vea este enlace angular.io/api/core/ChangeDetectorRef#detectChanges y angular.io/guide/lifecycle-hooks, como puede ver, DOM permanece y el servicio en la memoria intentará aplicar cambios mientras el componente en sí fue eliminado.Puedes usar
this.cdref.markForCheck();
en lugar de
this.cdref.detectChanges();
en muchos casos. Pero el mejor enfoque es seguir los consejos de @ Al-Mothafarfuente
Lo tengo resuelto con:
fuente
Simplemente separe ChangeDetectorRef en el enlace del ciclo de vida de OnDestroy y verifique si ChangeDetectorRef se destruyó antes de ejecutar el método detectChanges
fuente
this.cd
se separará automáticamente al destruir. Y si no es así, como!this.cd['destroyed']
se prueba antesthis.cd.detectChanges()
ensomeFunction
, estarás seguro de poder acudirsomeFunction
ante cualquier circunstancia.Tienes que obtener el valor de suscriptor en una variable y darte de baja por la misma var. Consulte el siguiente código
Tenga en cuenta que tengo cambios de cancelación de suscripción en el método ngOnDestroy ().
fuente
Mi solución fue dar de baja a todos los observadores.
Suscripción:
Darse de baja con changeDetector.detach ():
Eso era necesario en mi código, también debo usar la funcionalidad ChangeDetectorRef, solo esas dos cosas muestran mi código sin errores.
fuente
En mi caso, fue una cuestión de mala gestión de la configuración de prueba asíncrona de la configuración y compilación de componentes.
Código que causa errores ...
Se arregló con ...
fuente
No está mucho relacionado con una pregunta específica, pero llegué aquí buscando en Google el mismo error, así que compartiré mi solución. El problema fue que estaba llamando
fixture.detectChanges()
adentrofixture.whenStable().then(() => {})
sin envolver la prueba dentro de unaasync
función.Antes de:
Después:
fuente
Simple:
fuente
Mi causa ocurrió cuando intentaba abrir un diálogo modal con NgbActiveModal. Al parecer llamar
.dismiss()
por su propiangOnInit()
causa esto.La solución fue esperar un tic antes del despido.
if (foo) setTimeout(() => this.modalInstance.dismiss());
fuente
Bueno, estas respuestas no me ayudaron. Encontré otra solución.
El componente secundario tiene una salida que se activa cuando se hace clic en el botón de cierre
Y el método "hideChildComponent ()" en el componente principal detecta cambios.
Espero que esto ayude a alguien.
fuente
Para mí, la única solución que funcionó es la siguiente:
Explicación:
fuente
Para evitar este error, en lugar de llamar a detectChanges (), intente ajustar el código de cambio de modelo de la siguiente manera:
fuente