Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Built-in v-model on <details> and <dialog> #495

antfu started this conversation in RFC Discussions
Discussion options

Summary

Support built-in v-model binding for the native <details> element and <dialog> element.

Links


Summary

Support built-in v-model binding for the native <details> element and <dialog> element.

Basic example

<script setup>
import { ref } from 'vue'

const show = ref(false)
</script>

<template>
  <details v-model="show">
    <summary>Summary</summary>
    <span>Details</span>
  </details>

  <dialog v-model="show">
    <form method="dialog">
      <button>OK</button>
    </form>
  </dialog>
</template>

When toggling the <details> or <dialog> element, the value of show should be reflected. Or once show has been modified, the details should expand/collapse automatically.

Motivation

Currently we support v-model built-in on input, textarea, select, which is convenient to bind the value to them. However, when it comes to <details> and <dialog>, v-model will throw and users would need to bind manually. Which could be a bit counterintuitive.

Since <details> and <dialog> are native elements, it makes sense to have built-in support for them.

For now, users would need to manually bind them as:

<script setup>
import { ref } from 'vue'

const show = ref(false)
</script>

<template>
  <details :open="show" @toggle="show = $event.target.open">
    <summary>Summary</summary>
    <span>Details</span>
  </details>

  <dialog :open="show" @close="show = false">
    <form method="dialog">
      <button>OK</button>
    </form>
  </dialog>
</template>

Detailed design

This is should be a compiler improvement, to be able to transform v-model on the <details> and <dialog> elements with open and @toggle.

Drawbacks

It might theoretically conflict if users managed to implement a nodeTransformer on the user land to support v-model on <details> or <dialog>. But we are not aware of any existing library doing this.

Alternatives

N/A

Adoption strategy

This is a new feature and should not affect the existing code.

Unresolved questions

N/A

You must be logged in to vote

Replies: 5 comments · 3 replies

Comment options

How about <dialog> ?

You must be logged in to vote
1 reply
@antfu
Comment options

antfu Apr 8, 2023
Collaborator Author

Nice call! Added to the RFC!

Comment options

antfu
Apr 8, 2023
Collaborator Author

Update: Implementation PR vuejs/core#8048

You must be logged in to vote
0 replies
Comment options

Concerning <dialog> element, they are two ways to open them: using open() or openModal() methods, which behave differently

What do you think about using a modelModifier to support both?

You must be logged in to vote
1 reply
@thedamon
Comment options

The native way of controlling dialog is quite strange to me (open attribute that is only for initial state and doesn't make it modal, open/openModal being separate functions instead of a modal attribute)

Abstracting that away into v-model and v-model:modal (or v-model.modal) would be really nice and avoid need of dom refs setting it up as well. The exact format of that abstraction is maybe less clear and hard to know what people would expect vs how closely to follow the native element behaviour. Should it be a modifier or a binding, should specification be required or open (vs modal) be the default?

Overall I think v-model for open and v-model.modal for openModal makes the most sense.

Comment options

As there are two states for the openness of these elements, they are similar to checkboxes from a data-binding perspective. For checkboxes, Vue supports various features beyond a basic boolean binding: e.g. true-value/false-value and binding Arrays and Sets. I can't find this mentioned in the current RFC, so I'm wondering whether these features are seen as undesirable/unnecessary for <details> and <dialog>, or are they just being left for a future iteration of the feature?

You must be logged in to vote
1 reply
@thedamon
Comment options

I didn't realize that about checkbox models! I imagine it would make sense to handle these the same way.

Comment options

I've been thinking about a potential pattern with dialogs to support async reactivity awaiting the users confirmation. In this example, value would only be updated when the user clicks confirm.:

<script setup>
import { ref } from 'vue'

const show = ref(false)
const value = ref(null)
</script>

<dialog v-model="value" #default="{ internalValue }" modal :open="show">
  <form method="dialog">
    <input v-model="internalValue" />
    <button value="cancel">Cancel</button>
    <button>Confirm</button>
  </form>
</dialog>

This is considering the native dialog has a returnValue

Handling this pattern with custom components would benefit from #523. Supporting the native dialog would need some sugar, and an intuitive way for the input's v-model of the temporary state for returnValue. Am not sure if the scope slot syntax on a native element is the answer, or am overlooking a better option.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
6 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.