How to handle two-way data binding with fragment masking/colocation #179
-
I am enjoying working with this library, but have a more general question about the best workflow regarding two-way data binding.
<template>
<div class="column">
<div class="row heading">{{ trainerModel.person.name }}</div>
<div class="row">
<input v-model="trainerModel.license"/>
</div>
<div class="row">
<PersonSelect :model-value="trainerModel.person" @update:model-value="onTrainerPersonUpdated"/>
</div>
</div>
</template>
<script setup lang="ts">
const TrainerQuery = graphql(`
query TrainerQuery ($id: ID!) {
license
person {
name
...PersonSelectFragment
}
}
`, [PersonSelectFragment]);
const trainerModel = useQuery(TrainerQuery, {id: 1});
function onTrainerPersonUpdated(person: ???) {
trainerModel.person = person; // How can i assign the updated fragmentRef, but also update the properties the parent uses itself?
}
</script>
<template>
<SelectSearch :model-value="personModel" :options="personOptions" @update:model-value="onPersonUpdated" @filter="onFilter"/>
</template>
<script lang="ts">
export const PersonSelectFragment = graphql(`
fragment PersonSelectFragment on Person {
id
name
email
}
`);
</script>
<script setup lang="ts">
const personOptions = ref<ReadonlyArray<ResultOf<typeof PersonSelectFragment>>>();
const FindPersonsQuery =graphql(`
query FindPersons ($term: String!) {
persons: findPersons(term: $term) {
...PersonSelectFragment
}
}
`, [PersonSelectFragment]);
function onFilter(term: string, update: unknown) {
const res = await useQuery(FindPersonsQuery, {term});
update(() => personOptions.value = readFragment(PersonSelectFragment, res.data.persons))
}
function onPersonUpdated(person: ResultOf<typeof PersonSelectFragment>) {
// What do i emit here? maskFragments is discouraged, but i somehow need to update the parent object
}
</script> This is an imaginary stripped-down example, so it might not be 100% correct or make sense, but it should convey the issue i have. I am building an Admin UI where data can be edited/changed. In this example you can assign a (different) Person to a Trainer (not really sensible, but an easy example). I've encapsulated the select search/filter for persons in a separate component, since persons can be swapped in multiple places. I think my setup with the fragments in the
Does anyone have any experience dealing with this kind of issue? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I'm not sure if I'm 100% following, but Meaning, suppose we're trying to fill in The problem is that the sub-component currently uses just Conceptually speaking, you want to enforce that So, in my opinion, this is a good limitation, as you're trying to enforce that Basically, though, what I'd do is either:
|
Beta Was this translation helpful? Give feedback.
I'm not sure if I'm 100% following, but
trainerModel.person = person
seems like a bit of an icky idea to me. That said, I think there's no specific problem here, except that you have, conceptually speaking, a circular fragment dependency.Meaning, suppose we're trying to fill in
person: ???
.The problem is that the sub-component currently uses just
PersonSelectFragment
to select data.But the parent component defines
name
, i.e. its own selection set.Conceptually speaking, you want to enforce that
person: ???
is typed in such a way that reconciles both. This should cause you trouble, basically, because you're trying to reassigntrainerModel.person
.So, in my opinion, this is a good limita…