Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content driven components #9

Closed
jimafisk opened this issue May 6, 2020 · 1 comment
Closed

Content driven components #9

jimafisk opened this issue May 6, 2020 · 1 comment
Labels
enhancement New feature or request high high priority

Comments

@jimafisk
Copy link
Member

jimafisk commented May 6, 2020

Users should have the flexibility to load components based on the keys in their content structure (JSON).

Example JSON structure
{
  "title": "Anything",
  "components": [
    {
      "hero": {
        "slogan": "Something",
        "image": "/path/to/image.png"
      } 
    },
    {
      "grid": {
        "title": "Grid title",
        "items": [
          {"img": "/path/to/image1.png", "link": "/path/to/page1"},
          {"img": "/path/to/image2.png", "link": "/path/to/page2"},
          {"img": "/path/to/image3.png", "link": "/path/to/page3"},
        ],
      }
    },
    {
      "quote": "To be or not to be..."
    },
    {
      "slider": [
        {"scene": {"title": "whatever", "body": "more stuff"}},
        {"scene": {"title": "whatever", "body": "more stuff"}},
        {"scene": {"title": "whatever", "body": "more stuff"}},
      ]
    },
  ]
} 

In the example ^ there are 4 components: hero, grid, quote, slider. The challenge is dynamically loading the svelte component that corresponds to these using a simple text match since it will require having a component class instance.

In example, we're using the components key in the content source JSON. Ideally there will be a way to do this without having a required key.

@jimafisk jimafisk added enhancement New feature or request high high priority labels May 8, 2020
@jimafisk
Copy link
Member Author

This can be accomplished like so:

Example data source /content/pages/about.json
This is one example, but the data source key/value structure is flexible so do whatever works for you:
{
  "components": [
    {
      "component": "red",
      "fields": {"title": "I'm red"}
    },
    {
      "component": "green",
      "fields": {"title": "I'm green"}
    },
    {
      "component": "blue",
      "fields": {"title": "I'm blue"}
    }
  ]
}
Example dynamic component import in /layout/content/pages.svelte
<script>
  export components;

  async function loadComponent(component) {
    let path = "../components/" + component + ".svelte";
    return await import(path).then(res => res.default);
  }
</script>

{#if components}
  {#each components as { component, fields } }
    {#await loadComponent(component)}
    {:then co}
      <svelte:component this="{co}" {...fields} />
    {:catch error}
    {/await}
  {/each}
{/if}
Example imported component /layout/components/blue.svelte
<script>
  export let title;
</script>

<h1>{title}</h1>

<style>
  h1 {
    color: blue;
  }
</style>

However, the internal gopack does not support dynamic imports so you currently have to go into public/spa/content/pages.js after building and convert the .svelte extension in the loadComponent() function to be .js manually.

Currently Gopack actually checks that static import paths exist in the filesystem, this will be challenging to implement with dynamic imports since they can use variables that we'd have to get the value of. For now the easiest thing to do would be a simple string replace of .svelte to .js when they match regex import(); with single or double quotes inside the brackets and a sub-pattern of .svelte. This won't account for paths defined outside the import like in the example above and doesn't guarantee that the converted path won't throw an error. Down the road it would be nice to make this better.

It would also be nice to move the loadComponent() function into the /layout/scripts/ folder of the starter since this is something a lot of folks might be interested in using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request high high priority
Projects
None yet
Development

No branches or pull requests

1 participant