Compartir a través de


Desarrollar complementos de Office con Angular

En este artículo se proporciona instrucciones para usar Angular 2+ para crear un complemento de Office como una aplicación de una sola página.

Nota:

¿Tiene algo que aportar basándose en su experiencia con Angular para crear complementos de Office? Puede contribuir a este artículo en GitHub o enviar sus comentarios enviando un problema en el repositorio.

Para obtener un ejemplo de complemento de Office creado con el marco de Angular, vea Complemento de comprobación de estilo de Word basado en Angular.

Instalar las definiciones de tipo de TypeScript

Abra una ventana Node.js y escriba lo siguiente en la línea de comandos.

npm install --save-dev @types/office-js

El arranque debe estar dentro Office.initialize

En cualquier página que llame a las API de JavaScript de Office, el código debe asignar primero una función a Office.initialize. Office llama a esta función inmediatamente después de inicializar las bibliotecas de JavaScript de Office. Si no tiene código de inicialización, el cuerpo de la función puede ser simplemente símbolos "{}" vacíos, pero no debe dejar la Office.initialize función sin definir. Para obtener más información, vea Inicializar el complemento de Office.

Se debe llamar al código de arranque de Angular dentro de la función que asigne a Office.initialize. Esto garantiza que las bibliotecas de JavaScript de Office se inicialicen primero. El ejemplo siguiente muestra cómo hacer esto de forma sencilla. Este código debe estar en el archivo main.ts del proyecto.

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

Office.initialize = function () {
  const platform = platformBrowserDynamic();
  platform.bootstrapModule(AppModule);
};

Uso de la API de cuadro de diálogo de Office con Angular

La API de diálogo de complemento de Office permite al complemento abrir una página en un cuadro de diálogo nomodal que intercambia información con la página principal, que normalmente se encuentra en un panel de tareas.

El método displayDialogAsync toma un parámetro que especifica la dirección URL de la página que se debe abrir en el cuadro de diálogo. El complemento puede tener una página HTML independiente (diferente de la página base) para pasar a este parámetro, o bien puede pasar la dirección URL de una ruta en la aplicación Angular.

Es importante recordar, si pasa una ruta, que el cuadro de diálogo crea una nueva ventana con su propio contexto de ejecución. La página base y su código de inicialización y arranque ejecutan otra vez este nuevo contexto y las variables se establecen en sus valores iniciales en el cuadro de diálogo. Esta técnica inicia una segunda instancia de la aplicación de página única en el cuadro de diálogo. El código que cambia las variables en el cuadro de diálogo no cambia la versión del panel de tareas de las mismas variables. De forma similar, el cuadro de diálogo tiene su propio almacenamiento de sesión (la propiedad Window.sessionStorage ), que no es accesible desde el código del panel de tareas.

Activar la actualización de la interfaz de usuario

En una aplicación Angular, la interfaz de usuario a veces no se actualiza. Esto ocurre porque parte del código se ejecuta fuera de la zona de Angular. La solución es colocar el código en la zona, como se muestra en el ejemplo siguiente.

import { NgZone } from '@angular/core';

export class MyComponent {
  constructor(private zone: NgZone) { }

  myFunction() {
    this.zone.run(() => {
      // The codes that need update the UI.
    });
  }
}

Uso de Observable

Angular utiliza RxJS (extensiones reactivas para JavaScript) y RxJS introduce objetos Observable y Observer para implementar procesamiento asíncrono. En esta sección se proporciona una breve introducción al uso de Observables. Para obtener información más detallada, consulte la documentación oficial de RxJS .

Un Observable es, en cierto modo, parecido a un objeto Promise: lo devuelve inmediatamente una llamada asincrónica, pero no se puede resolver hasta un tiempo después. Sin embargo, mientras que un Promise es un valor único (que puede ser un objeto de conjunto), un Observable es una matriz de objetos (posiblemente con un solo miembro). Esto permite al código llamar a métodos de matriz como concat, map y filter en objetos Observable.

Inserción en lugar de extracción

El código "extrae" objetos Promise asignados a variables, pero los objetos Observable "introducen" sus valores en los objetos que se suscriben al Observable. Los suscriptores son objetos Observer. La ventaja de la arquitectura de inserción es que se pueden agregar nuevos miembros a la matriz Observable con el tiempo. Cuando se agrega un nuevo miembro, todos los objetos Observer que suscritos al Observable reciben una notificación.

Observer está configurado para procesar cada nuevo objeto (denominado objeto "siguiente") con una función. (También está configurado para responder a un error y una notificación de finalización. Consulte la sección siguiente para obtener un ejemplo). Por este motivo, Observable los objetos se pueden usar en una gama más amplia de escenarios que Promise los objetos. Por ejemplo, además de devolver desde Observable una llamada AJAX, la forma en que se puede devolver un Promiseobjeto , Observable se puede devolver desde un controlador de eventos, como el controlador de eventos "modificado" para un cuadro de texto. Cada vez que un usuario escribe texto en el cuadro, todos los objetos suscritos Observer reaccionan inmediatamente con el texto más reciente o el estado actual de la aplicación como entrada.

Espere hasta que se completen todas las llamadas asincrónicas.

Cuando desee asegurarse de que una devolución de llamada se ejecuta solo cuando todos los miembros de un conjunto de objetos Promise se ha resuelto, utilice el método Promise.all().

myPromise.all([x, y, z]).then(
  // TODO: Callback logic goes here.
)

Para hacer lo mismo con un objeto Observable, se utiliza el método Observable.forkJoin().

const source = Observable.forkJoin([x, y, z]);

const subscription = source.subscribe(
  x => {
    // TODO: Callback logic goes here.
  },
  err => console.log('Error: ' + err),
  () => console.log('Completed')
);

Compile la aplicación Angular con del compilador Ahead of Time (AOT)

El rendimiento de la aplicación es uno de los aspectos más importantes de la experiencia del usuario. Una aplicación Angular se puede optimizar utilizando el compilador Ahead of Time (AOT) de Angular para compilar la aplicación en tiempo de compilación. Convierte todo el código fuente (plantillas HTML y TypeScript) en código de JavaScript eficaz. Si compila la aplicación con del compilador AOT, no se producirá ninguna otra compilación en el tiempo de ejecución, lo que produce un procesamiento más rápido y solicitudes asincrónicas de plantillas HTML más rápidas. Además, el tamaño total de la aplicación se reducirá, ya que el compilador de Angular no tendrá que incluirse en el archivo distribuible de la aplicación.

Para usar el compilador AOT, agregue --aot al comando ng build o ng serve:

ng build --aot
ng serve --aot

Nota:

Para obtener más información sobre el compilador Ahead of Time (AOT) de Angular, consulte la guía oficial.

Compatibilidad con el control de vista web Trident

Los clientes de Office anteriores usan el control de vista web Trident proporcionado por Internet Explorer 11, como se describe en Exploradores y controles de vista web usados por los complementos de Office. Hay un par Angular consideraciones específicas que se deben tener en cuenta si el complemento necesita admitir estas versiones de Office.

Angular depende de unos pocos window.history Apis. Estas API no funcionan en la vista web trident. Cuando estas API no funcionan, es posible que el complemento no funcione correctamente; por ejemplo, puede cargar un panel de tareas en blanco. Para mitigar esto, Office.js anula esas API. Sin embargo, si está cargando dinámicamente Office.js, AngularJS puede cargar antes de Office.js. En ese caso, debe deshabilitar las window.history API agregando el código siguiente a la página deindex.html del complemento.

<script type="text/javascript">window.history.replaceState=null;window.history.pushState=null;</script>

Si el complemento admite controles de explorador basados en Trident, deberá usar la estrategia de ubicación hash en lugar de la estrategia de ubicación de ruta de acceso predeterminada. La estrategia de ubicación de ruta de acceso requiere compatibilidad con HTML5 que Trident no proporciona.