The status of the Office.js appointment remains updated even after the saveAsync callback is executed

Utilizing the Office JavaScript API for an Outlook add-in, I encountered a issue with some code designed to save an appointment and close its window. Despite saving the appointment through the API, I continue to receive a "Discard changes" confirmation dialog box. This problem specifically arises when editing an existing appointment and adding custom properties before saving it.

Below is the crucial part of my TypeScript code:

private saveAppointmentAndSetProperty(appointment: any): Observable<any> {
    const subject = new Subject<any>();

Office.context.mailbox.item.loadCustomPropertiesAsync(
        result => {
            if (this.isErrorResult(result)) {
                subject.error(result.error.message);
            } else {
                const properties = result.value;
                properties.set('MY_PROPERTY', true);
                this.saveCustomProperties(properties, subject,
                    () => this.saveAppointment(appointment, subject));
            }
        }
    );

    return subject;
}

private saveCustomProperties(properties: any, subject: Subject<any>, callback: () => void): void {
    properties.saveAsync(result => {
        if (this.isErrorResult(result)) {
            subject.error(result.error.message);
        } else {
            callback();
        }
    });
}

private saveAppointment(appointment: any, subject: Subject<any>): void {
    appointment.saveAsync((asyncResult) => {
        if (this.isErrorResult(asyncResult)) {
            subject.error(asyncResult.error.message);
        } else {
            appointment.close();
            subject.next(asyncResult.value);
            subject.complete();
        }
    });
}

The function `saveAppointmentAndSetProperty()` serves as the entry point to the code. Interestingly, executing the same code within `saveAppointment()` does not exhibit any issues.

Answer №1

There is a known issue with item.saveAsync in OWA that requires specific criteria to reproduce:

  1. The appointment must already exist
  2. It must have attendees

item.saveAsync() will provide the correct item ID but won't save changes made in the compose form to the service, and will clear the dirty state.

To persist custom properties, ensure the properties are saved to the service. If you are not using APIs that modify additional elements of the compose form (such as body, subject, location, attendees, etc.) for existing appointments with attendees, you can call saveAsync on CustomProperties. This action will save changes to custom properties in the service without prompting to discard changes unless you later call item.saveAsync().

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What defines a suitable application of the ref feature in React?

How can the ref attribute be effectively used in React? I understand that it is considered a shortcut that may go against the principles of React DOM, but I want to know the specifics of how and why. I'm currently evaluating if my use case justifies t ...

Are the fromPromise and toPromise functions in Rxjs resource-intensive?

Within my TypeScript application, I have come to a stage where one of my methods performs multiple operations with fromPromise and toPromise: myMethod(...): Promise<string> { return fromPromise(this.someService1.someMethod1(...)).pipe( m ...

What is the best way to iterate through all class properties that are specified using class-validator?

I have a class defined using the class-validator package. class Shape { @IsString() value?: string @IsString() id?: string } I am trying to find a way to retrieve the properties and types specified in this class. Is there a method to do s ...

Experimenting with a module reliant on two distinct services

I am facing an issue with a component that relies on a service to fetch data. The service also retrieves configurations from a static variable in the Configuration Service, but during Karma tests, the const variable is showing up as undefined. Although I ...

What happens when arithmetic operators are applied to infinity values in JavaScript?

Why do Arithmetic Operators Behave Differently with Infinity in JavaScript? console.log(1.7976931348623157E+10308 + 1.7976931348623157E+10308)//Infinity console.log(1.7976931348623157E+10308 * 1.7976931348623157E+10308)//Infinity console.log(1.797693134 ...

How can we incorporate methods using TypeScript?

I'm currently diving into TypeScript and encountering some challenges when trying to incorporate new methods into the DOM or other pre-existing objects. For instance, I'm attempting to implement a method that can be utilized to display colored te ...

"Combining the power of AngularJS2 beta with Spring Boot: the ultimate

I am currently using Atom 1.4.0 with the atom-typescript package to develop AngularJS2 modules in TypeScript. On the backend, I have a spring-boot application for handling the REST APIs. After making changes to the .ts files in Atom, it seems to compile t ...

Exploring Angular 10 Formly: How to Retrieve a Field's Value within a Personalized Formly Wrapper

Utilizing Angular 10, I have a formly-form with a select-field named session. This select field provides options from which to choose a dndSession. Each option holds key-value pairs within an object. I want to add a button next to the select-field that tr ...

What is the syntax for assigning a public variable within a TypeScript function?

I am finding it challenging to assign a value to a public variable within another function. I seem to be stuck. export class MyClass{ myVar = false; myFunction(){ Module.anotherFunction(){ this.myVar = true; } } } ...

results.map is not a valid method

Struggling to correctly display my axios response results in a table while learning React. Encountering an error - check it out https://i.sstatic.net/m80HJ.png Code snippet for API call: const listJobs = () =>{ axios.get( `${process.env.REACT_AP ...

Ways to narrow down const types

For the given scenario, I aim to enforce a specific format [string, number] for all function returns, while allowing varying input arguments for these functions. Access the Playground here type ReturnFormat = [string, number] type Fn = (...args: any[]) =& ...

Parsing JSON results in the return of two objects

I am analyzing a JSON file, expecting it to return Message[] using a promise. This code is similar to the one utilized in the Heroes sample project found in HTTP documentation { "data": [ {"id":"1","commid":"0","subject":"test1subject","body":" ...

What is the best way to loop through the keys of a generic object in TypeScript?

When I come across a large object of unknown size, my usual approach is to iterate over it. In the past, I've used generators and custom Symbol.iterator functions to make these objects iterable with a for..of loop. However, in the ever-evolving world ...

Having trouble with Next.js 13 GitHub OAuth integration - it keeps redirecting me to Discord instead of signing me in

There's a perplexing issue troubling my application... The implementation of OAuth 2 with GitHub, Discord, and Google is causing some trouble. While Google and Discord authentication works smoothly, attempting to sign in via GitHub redirects me to Di ...

The type 'IContact[]' given does not match the expected type 'FetchContactsSuccessPayload' for the parameter

I've been diving into my project involving react redux-saga with TypeScript and I'm facing an issue with a type error within my saga file. This is my first experience with TypeScript. The error originates from the saga.ts file, specifically this ...

What is the proper way to call document methods, like getElementByID, in a tsx file?

I am currently in the process of converting plain JavaScript files to TypeScript within a React application. However, I am facing an error with document when using methods like document.getElementById("login-username"). Can you guide me on how to referen ...

What are some ways to optimize the performance of a Select Box?

I am attempting to show a lengthy list of countries in an ion-select. Currently, there are 249 countries that I need to load. Unfortunately, the rendering performance is quite slow on my phone. <ion-list margin-top margin-bottom> <ion-item> ...

Guide on properly defining typed props in Next.js using TypeScript

Just diving into my first typescript project and finding myself in need of some basic assistance... My code seems to be running smoothly using npm run dev, but I encountered an error when trying to use npm run build. Error: Binding element 'allImageD ...

Setting up TypeScript in an Angular 2 project and integrating Facebook login

Currently, I am in the process of familiarizing myself with Angular 2 and typescript. Although things have been going smoothly so far, I have hit a roadblock while attempting to implement a Facebook login message. In my search for a solution, I stumbled up ...

What is the best way to implement a subquery using EXISTS in Knex?

I'm currently facing challenges while constructing a query using knex, specifically when it comes to incorporating the 'WHERE' clause with the condition EXISTS (SELECT * FROM caregiver_patient WHERE patient_id IN (0,1)). Below is the origin ...