#Hi all. I have an error I'm not sure
1 messages · Page 1 of 1 (latest)
The model in question is:
import { FFItemDataModel } from './baseItem';
const {
HTMLField, SchemaField, NumberField, StringField, FilePathField, ArrayField, BooleanField
} = foundry.data.fields;
export class JobModel extends FFItemDataModel {
static defineSchema() {
return {
...super.defineSchema(), // Merge with the base model schema
grants: new SchemaField({
list: new ArrayField(
new StringField({ required: true, initial: '' })
),
value: new BooleanField({ required: true, initial: false })
}),
}
}
}
The update that's causing the bother looks like this:
export async function deleteItemLink($doc, key, index) {
const itemList = [...$doc.system?.[key]?.list];
const spliced = itemList.splice(index, 1);
await $doc.update([`system.${key}.list`], spliced);
return spliced;
}
I'm confused by the validation error sort: must be an integer I'm not aware of having a sort column in my schema. So what does it mean?
Foundry itself has a sort in the document's schema. It sounds like something you're doing is adding a non-numeric sort key in the update somehow
Thx but I don't think I'm doing anything like that. Here's a trimmed down function that causes the same error:
export async function deleteItemLink($doc, key, index) {
const itemList = [...$doc.system?.[key]?.list];
await $doc.update([`system.${key}.list`], itemList);
}
So I fetch the list and update using the same list, and I get the sort error.
Have you tried logging the data before the update to see if that has clues?
Also, that .update syntax looks very wrong. Did you make your own method with the same name as the core function or something?
- logging before provides no clues
- I don't believe so. What's wrong with the syntax?
I mean the update happens and looks correct in the data despite the validation errors
Well, .update takes an object of key:value pairs and an optional object of options. You're handing it a single-string array and an array of items as the two args, rather than an object
My understanding was that it could also accept a string using dot notation as first argument and a value as second argument. At least I've been using it that way without trouble.
You may want this instead
.update({[`system.${key}.list`]: itemList})
Sure I switched it out to :
await $doc.update({system: { [key]: { value: 1, list: itemList } }});
But same validation error
If so, that's news to me, I've always needed to pass it an object as the data
I lied. The validation error disappears if I use the object syntax instead of the string dot syntax, although the update happens either way.
So I have two functions, one to add an item to the list and one to delete. Both were using the dot notation syntax. I was adding and deleting successfully except for the validation error.
Then I switched the delete to use the object syntax and that removed the validation error when deleting.
When I tried the same thing for the add function, it stopped working... so it doesn't update correctly using the object syntax.
i.e. this works:
await $doc.update([`system.${key}`], { value: 1, list: itemList } );
But for some reason, this does not:
await $doc.update({system: { [key]: { value: 1, list: itemList } }});
The latter does add an item without validation errors but the array item value is [object object] instead of a {uuid: "Item.ycgTsS5CrSfLgZ1O"}
Uh, that's weird
What does the itemList serialize to? Is it a store?
Ah I see up in the chat
Something else I just noticed is that although the update is updating the front-end, it's not persisting after a refresh
Actually I just noticed
Can you change the parameter from $doc to doc
For the function
Since the dollar sign is the actual store accessor
It may be confusing things
If I do that I get doc.update is not a function
I meant ONLY the parameter
huh?
Keep the dollar sign by the update function to actually access the document
Here, you have ($doc, key, index)
But I guess it doesn't change much if it already works in the other cases
$doc is just poorly named parameter. It's the output of the store, so it's just the document.
That's not entirely true, thinking about it but I think it's a red herring. $doc.update is just the foundry's update method
This makes me think you're doing something very janky, like trying to update a data model instead of the document itself or something
Where is your $doc coming from exactly as you go up the stack?
And it's key / values look like what you'd expect from an Item document
I will note I see the model being a boolean while you pass an integer but the sort thing is still befuddling me
I had it passing true before but I changed that to 1 because I thought that was what the validation error was about.
$doc is an Item. So I have an item in the game, I click on it, and $doc is a reference to that item within the code that manages the rendering of that item sheet.
Ok. I ask because this sounds like the sort of thing that generally would live either in the item class itself (and use this) or in a document sheet (and use this.document)
This is UI code, not the document code
Nor the actual app code, but the component of which the document is passed down to
It's code to update a document, one way or another
Sure just this is a completely different thing in this case.
So this is via the TJS svelte UI library. $doc is a reference to the underlying Foundry Item document, which is why it has the .update method on it.
I haven't neither extended or overridden the Item class itself, so it is the default Foundry implementation.
Ok, I'm just confused about how what you're describing is happening (especially the idea of passing a string+array as update args; looking at the method signature for Document.update I can't see how that could ever work.
Something odd is going on, based on what you describe (an update to a document should persist the data to the database, that's the whole point of it). My gut instinct is to blame the Svelte stuff somehow, but that is mostly because I have zero familiarity with it and don't know how it works like I do Foundry's side of things, lol
It feels like there's another layer of processing going on somewhere, somehow, that is mutating things before issuing the update, especially with what you're talking about regarding the data not being saved as-expected and the fact that the data you're talking about saving doesn't seem to line up with the schema of the DataModel you mentioned earlier
@dusky lark can you try logging doc.updateOptions
Documentation for TyphonJS Runtime Library (FVTT) 0.1.2
I’m AFK for an hour or so
It’s likely to be pebcak because these techniques are working in other modules / systems I’ve built on Svelte. But it certainly has me scratching my head.
ok so I built a standard hbs item sheet to do some testing.
The sort issue is caused by me incorrectly using the dot notation update syntax. I got confused.
This doesn't work:
await $doc.update([`system.${key}`], { value: 1, list: itemList } );
This does work:
await $doc.update({[`system.${key}`]: { value: 1, list: itemList }} );
That's all it was 🙂
I still don't know why the object syntax isn't working in my Svelte example though... will try work backwards now and see if I can figure that out.
Ok @kind island I've taken Svelte completely out of the picture and used the object syntax. It's still storing ['object Object'] instead of the object:
export default class ItemSheetStandard extends ItemSheet {
constructor(...args) {
super(...args);
}
get template() {
return `systems/foundryvtt-final-fantasy/assets/templates/${this.item.type}.hbs`;
}
activateListeners(html) {
super.activateListeners(html);
html.find('[data-action="testButtonClick"]').click(this._onTestButtonClick.bind(this));
const dropZone = html.find('[data-action="drop-handler"]');
dropZone.on('dragover', this._onDragOver.bind(this));
dropZone.on('drop', this._onDrop.bind(this));
}
_onTestButtonClick(event) {
event.preventDefault();
console.log("Test button clicked");
}
_onDragOver(event) {
event.preventDefault();
const dropZone = event.currentTarget;
dropZone.classList.add('drag-over'); dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('drag-over');
});
}
async _onDrop(event) {
event.preventDefault();
const originalEvent = event.originalEvent || event;
const data = JSON.parse(originalEvent.dataTransfer.getData("text/plain"));
const item = await Item.implementation.fromDropData(data);
const list = []
list.push({ uuid: item.uuid })
const key = 'grants'
await this.item.update({system : {[key] : { list }}});
game.system.log.d('item', this.item.system.grants.list) //- outputs `0: {['object Object']}
}
}
Is there something in my schema for that signature that's wrong? (See earlier post for the model)
I think it's probably that as I'm specifying that the ArrayField should contain a string, so it's converting the object to a string 😕
That sounds about right
grants: new SchemaField({
list: new ArrayField(
new StringField({ required: true, initial: '' })
),
value: new BooleanField({ required: true, initial: false })
}),
Oh. You're passing an object (with a UUID key and a value) into a StringField in an ArrayField. It's getting the string representation of the object.
Try list.push(item.uuid) instead
Yeah that was it. Ok. So a multi-layered flopped pebcak souflé... my specialty! 😅
You hit the drawback of data models. When you define a DataModel, you're locked into rigidly following that exact structure
Yeah, I'm finding the models significantly more difficult for me than ye olde template.json was. I find I'm going slower.
I mean, loosely typed languages are easy, you've just gotta not screw up 🤷♂️
But I'll probably get used to it