Fectching Data with WebComponent
Tags: webdev, javascript, vanjs
Published: 2023-07-07 12:45:44

Sometimes you have to display results coming from several requests.
Would not it be nice to simply use web component passing the url to be requested ?

```js
<fetch-randomuser data-num="5">
  <a href="https://randomuser.me/api/">
      Random Users
  </a>
</fetch-randomuser>
```

Here is the code :  ([Demo](https://flems.io/#0=N4IgtglgJlA2CmIBcAWATAOgBwDYA0IAzvAgMYAu8UyIGAFuWLCAaQPYB2hbCN7ssAIYAHYtQKFSAJx7MkAbQAMeRQF0CAMwgJCyeaA6CwiJLQZMWIdh0o2aAHQ4AeDfHKk6AWimCOUNmAArsRSAARQguSCnhyBYAC89iAArEkAfI6hoU6CoXRS8BqJIAzkokgA9BU+fgHB8FIYxhUiEBXpmVldAEq+-mChAKohhJ1OLRnOFa7uXjX99VKTjo6WxGTkEJy6pslIAIwAnJ77SIogAL54BkYmIPN1Ia0YAFa6rJy25DQQYMJsUnIoQAbr5QhoZAMkhgKqCOK9RiAVhxrIQgcBwhBgXhQgAjQLkcicHGEYS+HFJRaeUiCKRQJJIIYhADCtKgON+AHNQhdQvEQb4MFFOaMUdt0aF4H4cbj4JyIBweXyBRxkaigbioFjlQAKACUfLSeLlCp1WuB+r1yI0gRRm04oVZdJ1iwNwE6CHInSy5DocVxhm0ysWGGEEAogQKQr9YADgm0eG9oUWAH1DMZgyEMOn4BgtFI0YnFV1U-AwPHYJmGhgyxWi11kyEU6QIOQAJ5VxqwNg0+3wlvtgDcyKynsbDWbbOVsvlHB1wwaTqglqTVVC0Clm3bSfNOoxpCEhEIjIA5BubCeefWG+uwJy96FCFJSIzff7A5WLnrrw3dxi0W2CCnpQAAe5CeIIsAQJyHBIKQm4NJeVxJg2qY5ihoRWsWWRYQ2a6CDABRHjuWIPgeghHqeBFQERhBIT+XS7qW5baN+GFMU2A5tmx2GYZkSb4oSDo6hh7q8Q2nAHuGADWjL6oaoSQQ05A6gABgAEm2OIAJKKQMAAkwBobcFyqTxN5XqESSaUkSZYZ0UrLrhoQFOQkaKqmNJ0o4FzWraFBbIqC4Fi6Ixup0qI8Lm3b3oshDOa57njgWTQiDqS5Yb5qoooehChAAYm4HjBZKYGOXl6kACoALIADIAKIIMYNihGJWQUW2KKhNYHDwBQVCsgIuKCKQ0nyW1XRjrEQQjMqABy-oNDqvoQIQGARFExDkNmcTOaObihFBHDScqK1rQAjoEDRtgAyiQfVElIIkgIISR6sOvFjgU53KoIADu8ZAjMHhqYZR3SfQBQaBcAD8RGBLA5CEPEhnTXFpl7YdB1EcIv0A62LnwOdCKcPqSZwhg1HLXQq04sFhA6jjGDw4j8XOVlWWOKQwREmAjVlpua1QIUCrwM9wNzH0jwNEkOKFbMwXvWs90BdsNCKGcnjJAAzEgOuXNcIA5jQFNvJY1hfDQa4AIIEmwnjW8IwiOeC8CRJG8BWRwY4psNxA4imaIjSd-LyKog54RUoQ3VEo3ggCj6PQq3K+xRnv-IQraBaKjhrltimhL1f14mn-wKkDCciM70qPoIwLpwUwJbMEoQOn78Ax8Hjg2nagXGrOOraQAIuFxaB7HEPCMEdA6qnxDvWuN1157PBQCXxCdFUEAaKEs9B6NGAIBwnK+qERr7IoigGr6MjF0XoT1VIMhPbZIDvZ0c+e-yy1ts7bA74PEefJ4j8hPGiKQycTwGhhuEHscRNwYE5G4fmzVyAACE2zaWXMPA0jJh6dESlIRUn8fK5yjkRR6ntDwajTjiUgNhGQ0gEKEIIiMIDCAQKETYxhRQ91VoqRyOp6FAn5PsUeWRt672EWfUIYjJR+CES1TwsiEpuCSrPduypx7B1DGwYQlpI6EzRACFesA1772kqQ7Ka5Ko0zyloThqJVpfFgB2eoeVVKelUqEaS8A2x-QBGvBUaI3Zr3-qEVS6pvEaATgUKAgQWzHy4XQT2+I-CcMzgAL1zMiG2UEKLJ0fAEVJgRtCbEVIQNssYeB5SJITeJ8FkklPSZ7LJOTvYHQAPK4heMqbpLwHoB1tMLLQvV2ShGEDIIknSd78n6Q9RBbgAAKUy2DtmdjM5EY5qLWz8DdDwVAEbwE6RwfKEACwiN3ltEkOI+E4nxuQaq8VDSdB1PnGGMC3luEqr8eAbACQ6juaEB5TzvyF3gMXO65A9R6kpjAN59kOlAg8L4JBUBO6UBzkixOkR4ArLWWwZUE0kFAiSKCWASRxqEzckQ5Jq0MApnJVeEcj4DpksgpS4E4iuh5IgAUpJqkzreLqXEhJntfTNLgK0iA2SMBJjHHlfkZ06GRgAGrKjWoyjlvFJE6mBKEAAhCA7qaruUNl1WtVeqrILAP5NzKQqrMYNhRcfKgGL4CKsUjAXZ6KDnxIQCcs5FyhF0FRW6qImKbnJmEBteAQ8AjxQwiQYg64AH6pAfyS1ZjrWwCdV0F1aL3VC3upQBFGFNVMv5MCcth9nFSgaGtGJUh6ojRnpWeIRpYB6pVQ6mFSYspZGQtlLISROBF0pbm1qdK1pQRCb1FKU9CBtoNEOzmHA84Rrxas9ceVcgcPjIqNgPSHrJJbpMglMy3mbvxUSA0q1QgvB5qEeZFBQyrPWe0tc57pkaCvbim9bA715SJqU8lm4uGEu-WwS9wAvx4gJLXeueV9h4jbJQdcioJUsIVDKqg8GWlyuxUel4AHlRQcvUHSgAHEUKs3cqHD5Ac0KT3B-FMUGUwpkZJRrdBLrxatgIyBjObrxWsgoJjgrZhOdFxAqLUx9jyhDDteWdtgG2MiUz5GjB0iTxoGFWhSwJsxsGFpVX+nsYH6sZPfSq8AwJ6q00Caiup+g4gwG5jw2gaJSgNB23eEUaZmIKPCDQQgVLaQ4KM1s3E8wAhbSDDzZiFL9Epk7RyzIAvLiTOR39CWoA+eNdx0jMCZMKNyzidNRouWhFfGwXTIbPMwvMrAsADmuGCBFMqe++KQJth1DqHMrm3O0hFD5o0E0xzyHPaIQbGBctBdUGR1Zl7huECUAtj5oQr62tbj0orikpAdfU7BmbK3VAegOv0ZU-huaoNmwUXFKDNz9duM5Jtu8JvSXKwt8J-Saw2AgR6nUU22atXlQdLalAwj8n6PIaSC2jX8hTMMkWYzQgWaSwEWHC39OMgq81jAW1raEggYJMWn2QSY11dl+z23CurINCV5c2IQTMYh0tLlOJ+h9t4smz2VOlu-qqxmnbJH6d4lkzqNzGBgTyCSMLUQSR1C7yl-L55vmvmEnZ7LkAGhFeS7c6rmFnOAjc4bLz1lmunpcs6AOrGQIodeuXC50IUu5vec6Lqz+BoqafxxFIA0+E7YO1SzXSRmiOBrMlH8bcxZCGKikD5HEwASVyWFDiHMo22ucgwIz2eyPRlUHTy9r8WyDoOMh2g2TydPWKqNGtRn1eNU56r-JvMZSlq4gUridaAQYYYFWsyMdD0qCtcCDG3FunPXyV8+Ng6Bbw24sINbJ+ggOyh1d6G116LN2EDO8Wef2-F9aPz6LekxY3s6jHJ38J98oUhrDYfzFy+fBtjzKF6qaVy8NEr34avjXQefQHTAApiq7G5gC8j8i4hg5AhFy6bTh5j+T64Mqq6pT6Jry+ZQAMrkpgrO5S4gHwCiCoFmhJYYCia5qU4AKwEBCGrGpc4YS6pUEDBGqhBI5+Ao4j4YRZDJYFD7rwQADqrYM83el2SqtWAQ-WEKumMKEc5u3BZYbA9c+oMoPeemLBJ+YyNunQF+CqrcO8B+Raz+q+BoWaUATGmaWB2qa6V+LenIAA4qQMyG2AePAOFk8sqBfJfI4LRovpVGwPYaXhqLJrqCrgQWrmNudkDP5FdqEbovos5F9B6gjJcnwkgSgeWGgSQfxqbqmrvCzCIojuoSPtSklGHBEeLr-kkvyMAaroyKAc1jVnVnkWCnwrbtoeDroeEKEWajipir4fYb9N6nsn6kcoGucmiH+r0X4aQDchhNPkaBMR6n0aQDFs2q2oCu3lID-nJiNiSDvkscfmwQXnlgxFkA3sfPYY4c4a4YmrxPXjYWtIukITYezAQmorSmcdnv0FYo4LZv8ICJ0RoIIEka1NRDiMKIQLsbijKLJjKCaBwDiI5FlMrBsNnDQPsOiWcAbDcMYDQAiObJ8JuDQFiUbLcLiaQEePiTYISaYLiMZh2BNKccHJyDIMMoyHQIQF2mgNrMoKEMkDgAAKQ4iHD8nvwcBrpUheRrwTRaikhCBtiMgha2YfSnGBINCMhoDCAgRFJQRrxQScgMDMl+LKkTLUTJyMgXyanGnlgHYKieC0lCRgDqmKCWmdB-TQC+ioDJDOkgRWnDYKiMiKCKR2y+k2kcB2lrK8xOkunFiQTQRhmthljHjwRUlSDGmcgiBRk+nSaqlSDeAEQQDBCMg4DRlZD8AAiMh-Q0yUDGnDSjTMn-J+Bskck6hck8l8mCm8nJAikfTikhDUhThcgAEql0gNB5laiFm8mKD8nGkpLQQMCMheklnArul0DVaTlLnfGxB9mSldCCREiKgMm1nST1msl5DNmtk4jtk4goBdmim7k5lWacDwDGndQ8DlmVkJkvlkgwBmmyLekvm0kjm5k+DjkKZenTnej2rcBSBIBlwpkvmbkSx5m1AzQNAFzSmrT7rym4jdijQhmzjhkOmZnGmgTgSxkwRwQISplaGfCeBtKMjawalZlinIhwpeZHhDmYiymr4KkIDMVZCKkgSeBagFD8KMI8BxAcBpkZm8lLnfnbHEWukrmMiHBTk1lMksmNlnmcncmXkCnXm3kAU5ljkFkKbFnMVrr97CwtQTRulQAekADs3pPkyJD0qJpg2sOABwaAlw6gJJOJpg3QBBQg8EtUCo0kng8sxUIQ1qHAAAUjdJcEAA))

```js
import van from "./van.js"

const { div, button, span, "user-card": UserCard, img } = van.tags
const { end, begin } = van

const bdiv = () => begin(div())

function Card(user) {
  let
    thumbnail = user.picture.thumbnail,
    user_name = user.name.first,
    user_email = user.email,
    user_city = user.location.city;

  let user_card = begin(UserCard())
    // identity
    div({ class: 'ident' },
      img({ src: thumbnail }),
      div({ style: 'text-align:center' },
        user_name
      )
    )
    // address
    div({ class: 'address' },
      div(user_email),
      div(user_city),
    )
 
    button (
      {
        onclick: () => alert(`Hy, I am ${user_name}`),
      }, "Hy"
    )

  end()
  return user_card
}

function Users(users) {
  console.log(users)
  return users.map(Card)
}

class FetchUser extends HTMLElement {
  async connectedCallback() {
    let numusers = Number(this.dataset.num)
    let link = this.querySelector("a");
    let req = await fetch(`${link.href}?results=${numusers}`)
    let resp = await req.json()
    van.add(this, Users(resp.results))
  }
}

customElements.define("fetch-randomuser", FetchUser);
```