$actor.toObject() for a TJSDocument isn't reactive

I'm creating an actor in memory and assigning that to the TJSDocument on my application
export default class PCApplication extends SvelteApplication
{
/**
* Document store that monitors updates to any assigned document.
*
* @type {TJSDocument<foundry.abstract.Document>}
*/
#documentStore = new TJSDocument(void 0, { delete: this.close.bind(this) });

constructor(object) {
super(object);

// Define document store property
Object.defineProperty(this.reactive, "document", {
get: () => this.#documentStore.get(),
set: (document) => {
this.#documentStore.set(document);
},
});
this.reactive.document = object;
}

static get defaultOptions() {
const title = this.title;
return foundry.utils.mergeObject(super.defaultOptions, {
id: 'foundryvtt-actor-studio-pc-sheet',
title: game.i18n.localize('GAS.ActorStudio')+' - '+game.i18n.localize('GAS.PCTitle'),
classes: ['gas-actor-studio'],
width: 650,
height: 600,
headerIcon: 'modules/foundryvtt-actor-studio/assets/actor-studio-logo-dragon-white.svg',
minWidth: 500,
padding: 0,
resizable: true,
focusAuto: false,
minimizable: true,
svelte: {
class: PCAppShell,
target: document.body,
props: function () {
return { documentStore: this.#documentStore, document: this.reactive.document };
},
},
});
}
export default class PCApplication extends SvelteApplication
{
/**
* Document store that monitors updates to any assigned document.
*
* @type {TJSDocument<foundry.abstract.Document>}
*/
#documentStore = new TJSDocument(void 0, { delete: this.close.bind(this) });

constructor(object) {
super(object);

// Define document store property
Object.defineProperty(this.reactive, "document", {
get: () => this.#documentStore.get(),
set: (document) => {
this.#documentStore.set(document);
},
});
this.reactive.document = object;
}

static get defaultOptions() {
const title = this.title;
return foundry.utils.mergeObject(super.defaultOptions, {
id: 'foundryvtt-actor-studio-pc-sheet',
title: game.i18n.localize('GAS.ActorStudio')+' - '+game.i18n.localize('GAS.PCTitle'),
classes: ['gas-actor-studio'],
width: 650,
height: 600,
headerIcon: 'modules/foundryvtt-actor-studio/assets/actor-studio-logo-dragon-white.svg',
minWidth: 500,
padding: 0,
resizable: true,
focusAuto: false,
minimizable: true,
svelte: {
class: PCAppShell,
target: document.body,
props: function () {
return { documentStore: this.#documentStore, document: this.reactive.document };
},
},
});
}
Then to open the application:
new PCApplication(new Actor.implementation({ name: 'Name1', folder: folderName, type: actorType })).render(true, { focus: true });
new PCApplication(new Actor.implementation({ name: 'Name1', folder: folderName, type: actorType })).render(true, { focus: true });
PCAppShell does:
export let documentStore;
setContext("#doc", documentStore);
export let documentStore;
setContext("#doc", documentStore);
Then later in another componentI do this:
const doc = getContext('#doc')
$doc.name = "Name2"
console.log($doc.name) //<-- outputs "Name2"
console.log($doc.toObject().name) //<-- outputs "Name1", which is unexpected.
const doc = getContext('#doc')
$doc.name = "Name2"
console.log($doc.name) //<-- outputs "Name2"
console.log($doc.toObject().name) //<-- outputs "Name1", which is unexpected.
3 Replies
TyphonJS (Michael)
Well, this is a not knowing how Foundry works problem. The last code sample above would occur regardless if the in-memory document was wrapped by TJSDocument. IE the $doc.toObject().name has nothing to do w/ TRL per se. I haven't worked with in memory docs, so perhaps you should ask some questions on the mothership. Even with in-memory docs you might have to invoke update though it won't go through any sort of DB process. In memory docs will not be reactive because the reactivity that is captured is the underlying Foundry DB update cycle. An in-memory doc won't be connected to the DB part. Possibly it might work, but you must invoke update on the in-memory doc; try that out. Also in your code there are several copy / paste things from way earlier example code. For TJSDocument if you don't have a document to pass in the constructor you can pass the options object as the first parameter, so no need for the leading void 0. Also in regard to mounting components if you have stores and other things that you are going to set as context items you can pass a Map or even object into the component from the Svelte configuration object in defaultOptions via the context attribute. No need to pass the prop then set the context in the mounted component. Just better / more efficient configuration.
geoidesic
geoidesicOP6mo ago
Ah. Ok thank you. All very useful. I already know how to update an in-memory object in Foundry, I just hadn't grokked that TJSDocument is specifically connected to the DB update and doesn't have anything to do with in-memory updates. So that was an easy fix! Thanks for the info about the efficiency improvements I'll have a go at refactoring around that too.
TyphonJS (Michael)
It's not connected to the DB per se, but ClientDocumentMixin / DB update mechanism that force renders a "registered" app is the only callback chain in Foundry. `TJSDocument fakes being an app and registers with this mechanism.
Want results from more Discord servers?
Add your server