Alpine: Data binding with alpinejs

Created on 29 Jan 2020  路  8Comments  路  Source: alpinejs/alpine

I wonder if it would be possible to clarify how to pass and bind data from javascript functions into the alpinejs data models. This is a concept I'm finding really hard. I can get static data to bind but once it comes to modifying it (especially with promises), I don't know how to bind or update the data to the alpinejs front end components.

Here is an example of my struggles with this in a codepen
https://codepen.io/danfascia/pen/zYxXXXM?editors=1011

I suspect I've got the philosophy really wrong here but would value some guidance.

Most helpful comment

You don't need point to this in html, all vars in component points to this. or to window..
In video() function you have this only in scope object, not in function itself.

function video() {
  const iframe = document.querySelector('iframe');
  const player = new Vimeo.Player(iframe);
  const title = 'This title should get replaced'
  const status = false

  return {
    title: title,
    status: status,
    getTitle(){
      player.getVideoTitle().then( t => {this.title = t } )
    },
    play(){
      player.play()
    },
    init(){
      player.on('play', s => {
        this.status = true
      })

      player.on('pause', s => {
        this.status = false
      })
    },
  };
}
<main x-data="video()" x-init="init()">
   ....
  <button @click="getTitle()">Title</button>
  <button @click="alert(status)">Status</button> <!-- I don't know what you doing here -->
  <button @click="play()">Play</button>
</main>

All 8 comments

You don't need point to this in html, all vars in component points to this. or to window..
In video() function you have this only in scope object, not in function itself.

function video() {
  const iframe = document.querySelector('iframe');
  const player = new Vimeo.Player(iframe);
  const title = 'This title should get replaced'
  const status = false

  return {
    title: title,
    status: status,
    getTitle(){
      player.getVideoTitle().then( t => {this.title = t } )
    },
    play(){
      player.play()
    },
    init(){
      player.on('play', s => {
        this.status = true
      })

      player.on('pause', s => {
        this.status = false
      })
    },
  };
}
<main x-data="video()" x-init="init()">
   ....
  <button @click="getTitle()">Title</button>
  <button @click="alert(status)">Status</button> <!-- I don't know what you doing here -->
  <button @click="play()">Play</button>
</main>

Thanks so much for your help, I've updated my example above and added a few more features such as progress update binding.

Your example has been really useful in showing me the slightly different way of binding data Alpine needs. I actually really like this approach over the Vue way.

Thanks for pitching in @rzenkov!

I realize this is a closed issue but I'm seeing a similar thing. The suggestion above doesn't help me.

I'm trying to populate data via the Userbase (https://userbase.com) API in a function called from x-init and the variable I'm setting doesn't appear to be reactive.

Here are the operative bits from inside my component function:

       // this is the callback for the open userbase database
       changeHandler (updatedItems) {
          this.items = updatedItems
          console.log('this.items', this.items)
        },

        // this gets called on click
        getTodos () {
          userbase.openDatabase({ databaseName: 'todos', changeHandler: this.changeHandler })
            .catch((e) => console.log('Error: ', e))
        },

So far I haven't found the right combination of code to make this.items reactive in the DOM. The console.log shows what I'm expecting but the DOM never updates.

Right now I just have <span x-text="items.length"></span> It displays 0 initially because items is initialized as [] but then it never updates (unless I force a non-userbase-related action).

I'm sure it's just something I'm not understanding about userbase and promises. Any thoughts?

Really loving Alpine JS a lot so far.

@richcorbs Maybe you need to pass in the updatedItems like this this.changeHandler(items) :thinking:
Try this:

openDatabase({ databaseName: 'todos', changeHandler: (items) => { this.changeHandler(items) } })

@the94air Thanks for the idea.

The problem isn't that the updatedItems don't make it to the changeHandler. The console.log outputs what I'm expecting.

Maybe this isn't what I think it is in the callback?

@the94air Your suggestion totally worked! Thanks!

Do you understand why?

@richcorbs I think it's working because the items didn't reach the callback function. Just like when you don't call the event when using an event handler onclick="clickHandler(event)". The event will be undefined inside clickHandler function if there is not event param.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zaydek picture zaydek  路  3Comments

dkuku picture dkuku  路  5Comments

hkan picture hkan  路  3Comments

imliam picture imliam  路  5Comments

andruu picture andruu  路  3Comments