Home > other >  How can I use "await" inside of AlpineJS events?
How can I use "await" inside of AlpineJS events?

Time:08-20

I have an AlpineJS function that retrieves an image from URL, but is working only on x-data and not inside an @click event

async function loadPostImageForShare() {
            let images = [];
            const imgUrl = 'https://res.cloudinary.com/worldpackers/image/upload/c_fill,f_auto,q_auto,w_1024/v1/guides/article_cover/dtceexjjoji0w1ikkp2k';
            if (imgUrl) {
                fetch(imgUrl)
                    .then(res => res.blob()).catch(err => {
                    console.log(err);
                }).then(blob => {
                    const file = new File([blob], 'Post.png', blob)
                    images.push(file)
                }).catch(err => {
                    console.log(err);
                });
            }
            return images;
        }
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<li >
      <button  id="share-btn"
              x-data="{tooltip : false, tooltipText : ''},
                      images = await loadPostImageForShare();"
              @click="if (navigator.share) {
                      navigator.share({
                         title: 'Share a post',
                         text: 'Test, share post using alpineJS!',
                         url: 'https://stackoverflow.com',
                         files: images,
                      }).catch((error) => {
                         tooltipText = 'Something went wrong'
                         tooltip = true;
                         setTimeout(() => tooltip = false, 4000)
                         console.log(error);
                      });
                    } else {
                        tooltipText = 'Something went wrong'
                        tooltip = true;
                        setTimeout(() => tooltip = false, 4000)
                    }">
      <img  src="https://cdn.jsdelivr.net/npm/[email protected]/outline/share.svg" alt="Heroicons">
            <p >
                Share button
            </p>
      </button>
</li>
<div x-show="tooltip"
     
     x-transition:enter="transition ease-out duration-500"
     x-transition:enter-start="opacity-0 scale-90"
     x-transition:enter-end="opacity-100 scale-100"
     x-transition:leave="transition ease-in duration-500"
     x-transition:leave-start="opacity-100 scale-100"
     x-transition:leave-end="opacity-0 scale-90">
      <p  x-text="tooltipText">
      </p>
</div>

this example works by retrieving the image by calling the function on x-data

x-data="{tooltip : false, tooltipText : ''},
images = await loadPostImageForShare();"

but if I move that line to alpineJS @click event, the image is retrieved after the share action, so the share action has no image

 @click="images = await loadPostImageForShare();

async function loadPostImageForShare() {
            let images = [];
            const imgUrl = 'https://res.cloudinary.com/worldpackers/image/upload/c_fill,f_auto,q_auto,w_1024/v1/guides/article_cover/dtceexjjoji0w1ikkp2k';
            if (imgUrl) {
                fetch(imgUrl)
                    .then(res => res.blob()).catch(err => {
                    console.log(err);
                }).then(blob => {
                    const file = new File([blob], 'Post.png', blob)
                    images.push(file)
                }).catch(err => {
                    console.log(err);
                });
            }
            return images;
        }
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<li >
      <button  id="share-btn"
              x-data="{tooltip : false, tooltipText : ''}"
              @click="images = await loadPostImageForShare();
                      if (navigator.share) {
                      navigator.share({
                         title: 'Share a post',
                         text: 'Test, share post using alpineJS!',
                         url: 'https://stackoverflow.com',
                         files: images,
                      }).catch((error) => {
                         tooltipText = 'Something went wrong'
                         tooltip = true;
                         setTimeout(() => tooltip = false, 4000)
                         console.log(error);
                      });
                    } else {
                        tooltipText = 'Something went wrong'
                        tooltip = true;
                        setTimeout(() => tooltip = false, 4000)
                    }">
      <img  src="https://cdn.jsdelivr.net/npm/[email protected]/outline/share.svg" alt="Heroicons">
            <p >
                Share button
            </p>
      </button>
</li>
<div x-show="tooltip"
     
     x-transition:enter="transition ease-out duration-500"
     x-transition:enter-start="opacity-0 scale-90"
     x-transition:enter-end="opacity-100 scale-100"
     x-transition:leave="transition ease-in duration-500"
     x-transition:leave-start="opacity-100 scale-100"
     x-transition:leave-end="opacity-0 scale-90">
      <p  x-text="tooltipText">
      </p>
</div>

How can I make alpinejs "wait" for the function to finish?

NOTE: navigator.share only works in secure contexts (HTTPS)

CodePudding user response:

your async function needs to await the images response. try this

       async function loadPostImageForShare() {
            let images = [];
            const imgUrl = 'https://res.cloudinary.com/worldpackers/image/upload/c_fill,f_auto,q_auto,w_1024/v1/guides/article_cover/dtceexjjoji0w1ikkp2k';
            if (imgUrl) {
                await fetch(imgUrl)
                    .then(res => res.blob()).catch(err => {
                        console.log(err);
                    }).then(blob => {
                        const file = new File([blob], 'Post.png', blob);
                        images.push(file)
                    }).catch(err => {
                        console.log(err);
                    });
            }
            return await images;
        }

CodePudding user response:

Solution: Await was missing when fetching image in javascript function

It should be

await fetch(imgUrl)

async function loadPostImageForShare() {
            let images = [];
            const imgUrl = 'https://res.cloudinary.com/worldpackers/image/upload/c_fill,f_auto,q_auto,w_1024/v1/guides/article_cover/dtceexjjoji0w1ikkp2k';
            if (imgUrl) {
                await fetch(imgUrl)
                    .then(res => res.blob()).catch(err => {
                    console.log(err);
                }).then(blob => {
                    const file = new File([blob], 'Post.png', blob)
                    images.push(file)
                }).catch(err => {
                    console.log(err);
                });
            }
            return images;
        }
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<li >
      <button  id="share-btn"
              x-data="{tooltip : false, tooltipText : ''}"
              @click="images = await loadPostImageForShare();
                      if (navigator.share) {
                      navigator.share({
                         title: 'Share a post',
                         text: 'Test, share post using alpineJS!',
                         url: 'https://stackoverflow.com',
                         files: images,
                      }).catch((error) => {
                         tooltipText = 'Something went wrong'
                         tooltip = true;
                         setTimeout(() => tooltip = false, 4000)
                         console.log(error);
                      });
                    } else {
                        tooltipText = 'Something went wrong'
                        tooltip = true;
                        setTimeout(() => tooltip = false, 4000)
                    }">
      <img  src="https://cdn.jsdelivr.net/npm/[email protected]/outline/share.svg" alt="Heroicons">
            <p >
                Share button
            </p>
      </button>
</li>
<div x-show="tooltip"
     
     x-transition:enter="transition ease-out duration-500"
     x-transition:enter-start="opacity-0 scale-90"
     x-transition:enter-end="opacity-100 scale-100"
     x-transition:leave="transition ease-in duration-500"
     x-transition:leave-start="opacity-100 scale-100"
     x-transition:leave-end="opacity-0 scale-90">
      <p  x-text="tooltipText">
      </p>
</div>

NOTE: navigator.share only works in secure contexts (HTTPS)

  • Related