2017-06-12 4 views
1

Ich erstelle ein Excel-Add-in mit Angular und habe Bindungen für verschiedene Zellen erstellt. Ich habe ein Formular, das die Daten innerhalb dieser gebundenen Zellen anzeigt, und ich möchte, dass das Formular aktualisiert wird, wenn sich Daten in den Zellen ändern. In der OfficeJS Bibliothek verweist es mit:Verwendung von addHandlerAsync aus Office JS mit Angular

addHandlerAsync(Office.EventType.BindingDataChanged, <handler method>) 

https://dev.office.com/reference/add-ins/shared/binding.addhandlerasync

Allerdings, wenn ich innerhalb eines Winkelkomponente oder eine Dienstleistung, dass in TS zu tun versuchen, kann der Handler keine Methoden aus der Komponente aufrufen oder eine Dienstleistung wenn es ausgelöst wird. Es kann nur Office-JS-Methoden innerhalb des Handlers ausführen. Wie mache ich es so, dass ich eine Komponente oder eine Servicemethode innerhalb des Handlers auslösen kann?

Ein Beispiel für einen Anwendungsfall ist, wenn Sie in Ihrem Add-In jedes Mal etwas auslösen möchten, wenn sich in einer Ihrer Zellbindungen in der Tabelle etwas geändert hat, z. B. etwas in Ihrem Add-In anzeigen. Dies würde wie eine allgemeine Operation aussehen, die unterstützt würde. Und die Dokumentation zeigt etwas ähnliches in JS:

function addHandler() { 
Office.select("bindings#MyBinding").addHandlerAsync(
    Office.EventType.BindingDataChanged, dataChanged); 
} 
function dataChanged(eventArgs) { 
    write('Bound data changed in binding: ' + eventArgs.binding.id); 
} 
// Function that writes to a div with id='message' on the page. 
function write(message){ 
    document.getElementById('message').innerText += message; 
} 

Allerdings, wenn ich versuchen, etwas Ähnliches zu tun:

createHandlerOnA1(): Promise<IOfficeResult> { 
     return new Promise((resolve, reject) => { 
      this.workbook.bindings.getByIdAsync(this.bindingName, (result: Office.AsyncResult) => { 
       if(result.status === Office.AsyncResultStatus.Failed) { 
        reject({ 
         error: 'failed to get binding by id' 
        }); 
       } else { 
        result.value.addHandlerAsync(Office.EventType.BindingDataChanged, this.changeEvent, (handlerResult: Office.AsyncResult) => { 
         if(handlerResult.status === Office.AsyncResultStatus.Failed) { 
          reject({ 
           error: 'failed to set a handler' 
          }); 
         } else { 
          // Successful 
          resolve({ 
           success: 'successfully set handler' 
          }); 
         } 
        }) 
       } 
      }) 
     }) 
    } 

    addHandler() { 
    this.createHandlerOnA1() 
    .then((result: any) => { 
     this.feedback = result.success; 
    }, (result: IOfficeResult) => { 
     this.feedback = result.error; 
    }); 
    } 

    changeFeedback() { 
    this.feedback = 'hello' 
    } 

    // Excel methods 
    changeEvent(eventArgs: any) { 
     Excel.run(async (context) => { 
      const data = [ 
       ["Hello World"] 
      ]; 
     const range = context.workbook.getSelectedRange() 
     range.values = data; 
     await context.sync(); 
    }); 
    // Handler cannot run this 
    // this.changeFeedback(); 
    } 

Die Funktion, changeFeedback() kann nicht von innerhalb des change ausgeführt werden (EventArgs : jeder) Handler.

https://github.com/brandonkoch6/addHandlerAsyncError

ich versucht habe den Verweis auf die Handler zu ändern, so dass es die Bindung von ‚this‘ aufrechterhält, indem es wie folgt tun: Ich habe ein Beispiel Repo hier zu zeigen, das Problem gemacht

addHandlerAsync(Office.EventType.BindingDataChanged, (eventArgs:any) => this.changeEvent(eventArgs)) 

addHandlerAsync(Office.EventType.BindingDataChanged, this.changeEvent.bind(this)) 

Die reparieren es nicht. Also, ich bin ein bisschen ratlos was ich tun soll.

Jede Hilfe wäre willkommen. Ich denke, es hat etwas mit dem Kontextobjekt von 'this' zu tun, wenn der Handler ausgeführt wird. Es gibt einen [Optionen] Parameter als Teil der Handler hinzuzufügen, aber ich kann nicht alle Optionen scheinen in der Dokumentation zu finden:

https://dev.office.com/docs/add-ins/develop/asynchronous-programming-in-office-add-ins#passing-optional-parameters-to-asynchronous-methods

+1

Ich denke, es kann sein, weil Ihr Code außerhalb der Winkelzone ausgeführt wird. Du musst zulassen, dass ich innerhalb der Zone laufe. Überprüfen Sie [mein Code] (https://github.com/Hongbo-Miao/microsoft-graph-angular/blob/2a70ac9da98d870a01e09fdd16ddf6df0ca73584/src/app/%2Bhome/components/home.component.ts#L37) und [diesen Artikel ] (https://blog.Thoughtram.io/angular/2016/02/01/Zones-in-angular-2.html) –

+0

@HongboMiao Es hat funktioniert :) Danke, Hongbo! – codex

Antwort

1

Das Problem ist, da der Code ausgeführt wird aus Winkelzone.

Sie müssen den Code innerhalb der Zone ausführen lassen. Überprüfen Sie my code und this article um zu verstehen, wie es funktioniert.

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

// ... 

constructor(private zone: NgZone) { } 

myFunction() { 
    this.zone.run(() => { 
    // the code 
    }); 
} 

P.S. Ich habe ein Problem erstellt here. Ich werde das Dokument bald aktualisieren, wenn ich Zeit habe.

Verwandte Themen