Tengo una entrada de control deslizante de rango, que debería activar una propiedad computada asíncrona para mostrar. Mientras espera la respuesta, quiero mostrar una flecha giratoria. Vea a continuación lo que se me ocurrió. Siento que complico demasiado las cosas y, a veces, tanto la rueda giratoria como el título resultante se muestran al mismo tiempo (!). ¿Hay una mejor manera de hacer accesorios computados asíncronos con Alpinejs?
<script src="//unpkg.com/alpinejs" defer></script> <script> async function getTitle(id) { const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`) const data = await response.json(); await new Promise(resolve => setTimeout(resolve, 2500)) // adds some extra slowness return data.title.toUpperCase() } </script> <div x-data="{ todoId: 10, title: 'A PRELODED TODO TITLE' }"> <h3>Title formatter</h3> <p>Grab a todo via API and uppercases title </p> <input x-model="todoId" x-on:change="console.log('change!'); title = null" id="steps-range" type="range" min="0" max="50" step="1"> <div x-show="title !== null" x-html="title ?? (title = (await getTitle(todoId)))"></div> <div x-show="title === null">Loading ...</div> </div>Ajusté su ejemplo para mostrar una forma diferente de manejar el mismo problema. Está simplificado en el lado de Alpine.js y ajusté su función para ayudar con el problema de la etiqueta.
<script src="//unpkg.com/alpinejs" defer></script> <style> .error { color: red; } .success { color: blue; } .loading { color: orange; } </style> <div x-data="{ todoId: 10, title: 'A PRELODED TODO TITLE', error: false, loading: false, async getTitle(id) { this.success = true this.error = false this.loading = true this.title = 'Loading ...' await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`) .then(res => res.json()) .then(async(res) => { await new Promise(resolve => setTimeout(resolve, 100)) // adds some extra slowness if(res.id === parseInt(this.todoId)) { this.loading = false this.success = true this.title = res.title.toUpperCase() } return }).catch((e) => { this.loading = false this.title = e.message this.error = true }) } }" x-init="$watch('todoId', (newValue, oldValue) => { newValue != oldValue ? $nextTick(async() => { getTitle(todoId) }) : null })"> <h3>Title formatter</h3> <p>Grab a todo via API and uppercases title</p> <input x-model="todoId" id="steps-range" type="range" min="0" max="50" step="1" /> <div x-show="title" :class="{'error': error, 'success': !error, 'loading': loading}" x-text="title"></div> </div>