Skip to content

Instantly share code, notes, and snippets.

@marcus-at-localhost
Last active November 25, 2022 08:20
Show Gist options
  • Save marcus-at-localhost/68cbf0e637a39ddeca59199b717d46cb to your computer and use it in GitHub Desktop.
Save marcus-at-localhost/68cbf0e637a39ddeca59199b717d46cb to your computer and use it in GitHub Desktop.
[Alpine.js fetch data on `x-init`] #js #alpinejs
/*
Alpine Dev Tools: https://github.com/Te7a-Houdini/alpinejs-devtools
*/
function gistsData() {
return {
title: 'Latest Gists',
gists: [],
reload() {
sessionStorage.removeItem("gists");
this.gists = [];
this.init();
},
init() {
// Testdata, in case I hit my 60 calls per hour
/*let gists = [
{
"id": "8f6af49ffe693c15faca67a7f3bf1a31",
"html_url": "https://gist.github.com/8f6af49ffe693c15faca67a7f3bf1a31",
"description": "Test"
}
];*/
// Check if sessionData holds anything, so we don't need to hit the api
const gists = JSON.parse(sessionStorage.getItem("gists"));
if(gists){
// make it accessible to x-data
this.gists = gists;
console.log('sessionStorage', gists);
return;
}
console.log(new leptonParser().parse('[bla] #blub'))
// get gists and parse the description field
fetch('https://api.github.com/users/marcus-at-localhost/gists')
.then(response => response.json())
.then(response => {
console.log('fetched',response);
// I could use collect.js to manipulate the response further.
let gists = response.map((item) => {
// parser: https://codepen.io/localhorst/pen/ZEbqVZd
item.parsed = new leptonParser().parse(item.description);
return item;
});
this.gists = gists;
sessionStorage.setItem("gists",JSON.stringify(gists));
//console.log(this,response)
});
}
};
}
<div
class="h-full bg-gray-200 text-gray-800 p-4 lg:p-8"
x-data="gistsData()"
x-init="init()"
>
<header class="flex items-center">
<h1 class="flex-grow" x-text="title"></h1>
<button
class="py-2 px-4 rounded bg-blue-500 text-white flex-grow-0"
type="button"
x-on:click="reload()"
>
Reload
</button>
</header>
<ul class="list-reset flex flex-col">
<template x-for="gist in gists" :key="gist.id">
<li class="relative -mb-px block border p-4 border-grey">
<a x-bind:href="gist.html_url" x-text="gist.parsed.title"></a><br>
<small x-text="gist.parsed.description"></small>
</li>
</template>
</ul>
<p class="mt-3 text-xs">
<a href="https://developer.github.com/v3/gists/">API</a> ·
<a href="https://github.com/alpinejs/alpine">Alpine.js</a> ·
<a href="https://tailwindcss.com/docs">Tailwind</a> ·
<a href="https://tailwindcomponents.com/component/bootstrap-4-list-group-clone">Tailwind Components</a> ·
<a href="https://github.com/hackjutsu/Lepton">Lepton Snipped Management</a>
</p>
</div>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.4.6/tailwind.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/collect.js/4.25.0/collect.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/alpine.min.js"></script>
<script src="leptonParser.js"></script>
<script src="app.js"></script>
// borrowed from Lepton
// @link https://github.com/hackjutsu/Lepton/blob/0e6d75047c/app/utilities/parser/index.js
class leptonParser {
//constructor
constructor(payload='') {
this.payload = payload;
}
parse(payload){
this.payload = payload || 'No description';
return this.descriptionParser(payload);
}
descriptionParser (payload) {
const rawDescription = payload;
const regexForTitle = rawDescription.match(/\[.*\]/);
const rawTitle = (regexForTitle && regexForTitle[0]) || '';
const title = ((rawTitle.length > 0) && rawTitle.substring(1, regexForTitle[0].length - 1)) || rawDescription;
let tagStyle = 'legacy';
let customTags = this.parseCustomTagsLegacy(rawDescription);
if (customTags.length === 0) {
customTags = this.parseCustomTagsTwitter(rawDescription);
tagStyle = customTags.length > 0 ? 'twitter' : 'legacy';
}
const descriptionLength = tagStyle === 'legacy'
? rawDescription.length - customTags.length
: rawDescription.length;
const description = rawDescription.substring(rawTitle.length, descriptionLength);
return { title, description, customTags };
}
parseCustomTagsLegacy (payload) {
const regextForCustomTags = payload.match(/#tags:.*$/);
const customTags = (regextForCustomTags && regextForCustomTags[0]) || '';
return customTags;
}
// http://geekcoder.org/js-extract-hashtags-from-text/
parseCustomTagsTwitter (payload) {
var regex = /(?:^|\s)(?:#)([a-zA-Z\d]+)/gm;
var matches = [];
var match;
while ((match = regex.exec(payload))) {
matches.push(match[1]);
}
if(!matches.length){
return '';
}
return matches.reduce((acc, cur) => acc + ', ' + cur);
}
}
console.log(new leptonParser().parse('[bla] #blub #foo and #bar'));
@fulopattila122
Copy link

Thanks for the reply!

I tried your tip already, and the result was the same, but... actually it was almost that, and you helped me to find the solution:

{ initialize: () => {} } is not the same as { initialize() {} }

BAD:

const TimerWidget = {
    loading: true,
    initialize: () => {
        this; // <- window
    }
}

GOOD:

const TimerWidget = {
    loading: true,
    initialize() {
        this; // <- Proxy { <target>: {}, <handler>: {…} }
    }
}

Thanks again for the gist and for your help! 🙇

@marcus-at-localhost
Copy link
Author

I'm glad it worked out! See, these 5000 ways to declare functions/methods in JS and how they are scoped, that's just weird :). I have no idea how this {fun(){},foo: 'bar'} is possible. But it was on my plate to read up about that anyway - so thanks for bringing that up.

@fulopattila122
Copy link

fulopattila122 commented Mar 8, 2021

My teammate's reaction to the solution was also this:

image

😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment