Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

304
Vistas
Alpinejs async computed property with spinner

I have a range slider input, which should trigger an async computed property to display. While it is waiting on the response, I want to display a spinner. See below what I came up with. I sense I over complicate things and sometimes both the spinner and the resulting title displays at the same time (!). Is there a better way of doing async computed props with 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>

JSFIDDLE

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I have adjusted your example in order to show a different way to handle the same problem, It's simplified on the Alpine.js side and I've adjusted your function in order to assist the label problem.

<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>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda