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)