Faziki
Faziki

Reputation: 821

Using an external JSON file in Vue

I'm busy building a website for a friend of mine and he is not that computer literate. So I thought of an idea to make it easy for him.

I want to create a JSON file where I can save all the text and image paths in the JSON file so that he can go into the file and apply the changes that he wants instead of searching through the code (like you normally do) and applying the changes there.

I'm using the landing page as an example.

<template>
  <div class="home">
    <div v-for="data in myJson.hero" :key="data">
      <v-card tile flat>
        <v-img
          height="885"
          gradient="to top left, rgba(100,115,201,.13), rgba(25,32,72,.7)"
          :src="data.image"
        >
          <template v-slot:placeholder>
            <v-row class="fill-height ma-0" align="center" justify="center">
              <v-progress-circular
                indeterminate
                color="grey lighten-5"
              ></v-progress-circular>
            </v-row>
          </template>
          <v-row>
            <v-col cols="12">
              <div class="centered">
                <h2 class="display-2 text-center white--text">
                  {{ data.firstHeading }}
                </h2>
                <h1
                  data-aos="zoom-in"
                  class="display-4 font-weight-bold text-center white--text"
                >
                  {{ data.secondHeading }}
                </h1>
                <h3 class="subtitle-4 text-center white--text">
                  {{ data.subHeading }}
                </h3>

                <v-btn large class="btnCentered" outlined fab dark>
                  <v-icon>mdi-arrow-down</v-icon>
                </v-btn>
              </div>
            </v-col>
          </v-row>
        </v-img>
      </v-card>
    </div>
  </div>
</template>

<script>
import json from "../json/controller.json";
export default {
  name: "Home",
  data() {
    return {
      myJson: json,
    };
  },
  components: {},
  methods: {},
};
</script>

<style scoped>
.centered {
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.btnCentered {
  position: absolute;
  top: 250%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

My JSON file:

{
    "hero": [{
            "name": "heroImage",
            "alt": "telescopeImage",
            "image": "@/assets/background/telescope.jpg"
        },
        {
            "firstHeading": "HeroText",
            "secondHeading": "HeroText",
            "subHeading": "telescopeImage"
        }
    ],
}

I have done this before, but within a Vue.js file, not from another file

FirstTime

Somehow I'm doing it wrong... so, if someone kindly can enlighten my stupidity that would be great. And if someone knows of a better way please don't keep it a secret.

Edit**

I followed @Daniel_Knights advice it's working, KINDA... just that there is an unwanted feature that came with it.

Duplication

The landing page duplicates itself twice. Like a famous gaming company would say its a surprise mechanic. The text shows on the second one but not the image...

Edit*** X2

Figured out why it duplicates itself twice. but the image is still an issue.

The reason why it duplicated itself is that the JSON file wasn't like this.

    "hero": [{
        "name": "heroImage",
        "alt": "telescopeImage",
        "image": "@/assets/background/telescope.jpg",
        "firstHeading": "HeroText",
        "secondHeading": "HeroText",
        "subHeading": "telescopeImage"

    }],

Upvotes: 1

Views: 414

Answers (1)

Faziki
Faziki

Reputation: 821

Fixed it!

@Daniel_Knights pointed me in the right direction, you sir thank you for your enlightenment.

My issue was the JSON file was incorrect so it iterated itself twice. Secondly my image did not want to disply so I figured its to do with the path in the JSON file.

I created a method that adds @/ after the item that is a path.

My landing page

<template>
  <div class="home">
    <div v-for="data in myJson.hero" :key="data">
      <v-card tile flat>
        <v-img
          height="885"
          gradient="to top left, rgba(100,115,201,.13), rgba(25,32,72,.7)"
          :src="letterIcon(data.image)"
        >
          <template v-slot:placeholder>
            <v-row class="fill-height ma-0" align="center" justify="center">
              <v-progress-circular
                indeterminate
                color="grey lighten-5"
              ></v-progress-circular>
            </v-row>
          </template>
          <v-row>
            <v-col cols="12">
              <div class="centered">
                <h2 class="display-2 text-center white--text">
                  {{ data.firstHeading }}
                </h2>
                <h1
                  data-aos="zoom-in"
                  class="display-4 font-weight-bold text-center white--text"
                >
                  {{ data.secondHeading }}
                </h1>
                <h3 class="subtitle-4 text-center white--text">
                  {{ data.subHeading }}
                </h3>

                <v-btn large class="btnCentered" outlined fab dark>
                  <v-icon>mdi-arrow-down</v-icon>
                </v-btn>
              </div>
            </v-col>
          </v-row>
        </v-img>
      </v-card>
    </div>
  </div>
</template>

<script>
import json from "../json/controller.json";
export default {
  name: "Home",
  data() {
    return {
      myJson: json,
    };
  },
  components: {},
  methods: {
    letterIcon: function (path) {
      return require("@/" + path);
    },
  },
};
</script>

<style scoped>
.centered {
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.btnCentered {
  position: absolute;
  top: 250%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

My JSON file

{
    "hero": [{
        "alt": "telescopeImage",
        "image": "assets/background/telescope.jpg",
        "firstHeading": "HeroText",
        "secondHeading": "HeroText",
        "subHeading": "telescopeImage"
    }]


}

Upvotes: 1

Related Questions