Estoy trabajando para incorporar un calendario de eventos de JavaScript llamado FullCalendar en una aplicación de Aurelia. Tengo un módulo estándar de Aurelia llamado dashboard y he puesto la implementación del calendario en un archivo .js separado llamado calendar.js, y he creado un atributo personalizado llamado calendar. Estoy usando un atributo personalizado porque no hay una vista calendar adjunta, todo se genera en JavaScript.

Dado que el calendario no es visible cuando se carga la página (porque no está en la pestaña principal o activa), no se dibuja cuando el método attached() se activa en el código de atributo personalizado. Necesito poder observar un evento Bootstrap (haciendo clic en la pestaña) desde el atributo personalizado para activar un método .render para dibujar el calendario cuando finalmente se haga clic en la pestaña.

Aquí hay fragmentos relevantes de mi código:

dashboard.html:

<!-- Standard Bootstrap tabs -->
<ul class="nav nav-tabs" role="tablist">
                    <li role="presentation" class="active"><a href="#tab1" role="tab" data-toggle="tab">Projects</a></li>
                    <li role="presentation"><a href="#tab2" role="tab" data-toggle="tab" id="calselect">Calendar</a></li>
                    ...
                    ...
<!-- and further down the same page, the tab panes with their content -->
<div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="tab1">
        <!-- Table content here... -->
    </div>
    <div role="tabpanel" class="tab-pane" id="tab2">
        <div class="row">
            <div class="col-md-12">
                <div class="panel panel-white">
                    <div class="panel-body">
                        <div calendar calvisible.bind="calVisible"></div>
                    </div>
                </div>
            </div>
        </div><!-- Row -->  
    </div>
</div>

dashboard.js:

...
  constructor(http, dataRepository) {
    this.http = http;
    dataRepository.getProjects().then(projects => this.projects = projects);
    this.calVisible = false;
  };
...
  attached(){
    var cal = document.getElementById('calselect');
      $(cal).on('shown.bs.tab', (e) => {
        this.calVisible = true;
      });
  };

calendar.js:

 @bindable calvisible;

Bootstrap dispara un evento llamado 'shown.bs.tab' cuando se hace clic en una pestaña. id="calselect" hace referencia a la pestaña correcta. Cuando se hace clic en la pestaña, la propiedad vinculada this.calVisible se establece en verdadera. Posteriormente, calvisible está vinculado al archivo calendar.js.

Hay dos problemas que puedo identificar. Primero, desde la perspectiva de calendar.js, calvisible no existe hasta que se hace clic en la pestaña, lo que hace que el paquete web se queje pero no bloquee la aplicación. No pude detectar esto usando una instrucción if y no estoy seguro de por qué.

En segundo lugar, cuando se hace clic en la pestaña, aunque el valor de calvisible muestra true en el archivo calendar.js, no activa un evento de cambio que pueda observar allí, y eso es lo que Necesito activar un método .render para dibujar el calendario. Intenté usar @observable aquí, pero tampoco pude hacerlo funcionar. ¿Cuál es el enfoque correcto?

Solución

Aquí está el código ganador basado en la respuesta de @Fabio Luz a continuación:

bind(){
    this.calvisible = this.calvisible;
}

calvisibleChanged(){
    $(this.element).fullCalendar('render');
}
2
espressoAndCode 15 dic. 2016 a las 21:40

2 respuestas

La mejor respuesta

En esta situación, creo que debería utilizar un elemento personalizado en lugar de un atributo personalizado. Para resolver el problema de la falta de una vista , Aurelia te proporciona el decorador @noView, ver los documentos. Su código se vería así:

import {noView} from 'aurelia-framework';

@noView
export class Calendar {
   @bindable calvisible;

   bind() {
     //do your js magic here
   }

   calvisibleChanged() {
   }
}

Es posible que aún tenga algunos problemas con js. Actualice su código, vea qué sucede, cuénteme qué está pasando e intentaré ayudarlo más.

1
Fabio Luz 15 dic. 2016 a las 20:29

Lo siento, no puedo comentar. (La respuesta es la misma que la anterior de Fabio Luz, excepto un poco más sobre su error tipográfico)

¿Tiene un error tipográfico en su código? Veo en tu view que estás vinculando a calVisible pero es calvisible en viewModel Si es así, hazlo así

@bindable calVisible; // this was calvisible

Después de esto, simplemente puede hacer en su viewModel:

// Note that this will be called after the value changed
calVisibleChanged(newValue) {
    if (newValue) {
        // Do something when cal is shown
    } else {

    }
}
1
bigopon 15 dic. 2016 a las 21:00