0

in this vue example down below I'm trying to load the 'images' array from an external js file using vue only. I tried something similar to this post: How do I access data from an external file in Vue.js please? but it's not quite working for me (most likely because I'm doing something obvious wrong). Any advice on how to make that work very much appreciated.

I created a codePen for you in case you prefer to look at it this way. Thanks! https://codepen.io/FloydGekko/pen/eLoRBQ

<head>
    <style>
        [v-cloak] {
          display: none;
        }

        .imageBlock{
            width:100%;
            margin:10px;
        }
        div.polaroid {
            width:310px;
            height:440px;
            margin:10px;
            background-color: white;
            box-shadow: 6px 4px 8px 0 rgba(0, 0, 0, 0.2), 6px 6px 20px 0 rgba(0, 0, 0, 0.19);
            margin-bottom: 25px;
            border-radius: 18px
        }
        div.container {
            text-align: center;
            padding: 10px 20px;
        }
    </style>
</head>

<body>

<div id="vue" v-cloak>
    <h2 align="center">
        Show
    <select v-model="currentKind" @change="onChange">
        <option v-for="kind, index in kinds" :value="kind" :key="`kind_${index}`">{{kind ? kind : 'kind...'}}</option>
    </select>
    <select v-model="currentColor" @change="onChange">
        <option v-for="color, index in colors" :value="color" :key="`kind_${index}`">{{color ? color : 'color...'}}</option>
    </select>
        and
     <select v-model="currentShape" @change="onChange">
        <option v-for="shape, index in shapes" :value="shape" :key="`kind_${index}`">{{shape ? shape : 'shape...'}}</option>
    </select>
    </h2>

    <isotope
            id="root_isotope"
            ref="isotope"
            :options='options'
            :list="images"
            align="center">
        <div class="polaroid" align="center"
            v-for="(image, index) in images"
            class="imageBlock"
            :key="image.id">
            <a target="_blank"  :href="image.url"><img border="0" :src="image.pic" alt=""
            style="
                border-radius: 20px;
                display: block;
                margin-left: auto;
                margin-right: auto;
                width: 100%;">
            </a>
            <div class="container">
                <a target="_blank"  :href="image.url">
                <h3 align="center">{{image.title}}</h3>
                </a>
            </div>
        </div>
    </isotope>
    <h2 align="center">
        <button @click="reset">Show all</button>
    </h2>
</div>


<script src='https://unpkg.com/vue/dist/vue.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js'></script>
<script src='https://npmcdn.com/[email protected]/dist/isotope.pkgd.min.js'></script>
<script src='https://rawgit.com/David-Desmaisons/Vue.Isotope/master/src/vue_isotope.js'></script>


<script>
    let currentKind = null;
    let currentColor = null;
    let currentShape = null;

    var vm = new Vue({
        el: '#vue',
        data() {
            return {
                currentKind:'',
                currentColor:'',
                currentShape:'',
                options: {
                    itemSelector: ".imageBlock",
                    getSortData: {
                      id: "id"
                    },
                    sortBy : "id",
                    getFilterData: {
                        Finder: function(itemElem) {
                            let kindSearch = currentKind ? itemElem.kind.indexOf(currentKind) !== -1 : true;
                            let colorSearch = currentColor ? itemElem.color.indexOf(currentColor) !== -1 : true;
                            let shapeSearch = currentShape ? itemElem.shape.indexOf(currentShape) !== -1 : true;
                            return kindSearch && colorSearch && shapeSearch
                        },
                    },
                },

        //THIS IS THE ARRAY IM TRYING TO LOAD FROM AN EXTERNAL FILE
                images: [
                    {
                        id: 1,
                        kind: ['A'],
                        color: ['Green', 'Blue'],
                        shape: ['Square'],
                        pic: 'http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg',
                        url: 'http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg',
                        title: 'A',
                    },
                    {
                        id: 2,
                        kind: ['B'],
                        color: ['Green', 'Red'],
                        shape: ['Circle'],
                        pic: 'https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG',
                        url: 'https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG',
                        title: 'B',
                    },
                ],

            };
        },
        computed: {
            kinds(){
                let allTags = _.flatten(this.images.map(image => image.kind))
                return [''].concat(_.uniq(allTags))
            },
            colors(){
                let allTags = _.flatten(this.images.map(image => image.color))
                return [''].concat(_.uniq(allTags))
            },
            shapes(){
                let allTags = _.flatten(this.images.map(image => image.shape))
                return [''].concat(_.uniq(allTags))
            },
        },
        methods: {
            onChange: function() {
                currentColor = this.currentColor;
                currentShape = this.currentShape;
                currentKind = this.currentKind;

                this.$refs.isotope.filter('Finder');
                this.$refs.cpt.layout('packery');
            },
            reset(){
                currentColor = '';
                currentShape = '';
                currentKind = '';

                this.currentColor = '';
                this.currentShape = '';
                this.currentKind = '';
                this.onChange()
            }
        },
    });
</script>
</body>
</html>

https://codepen.io/FloydGekko/pen/eLoRBQ

2

1 Answer 1

0

It really depends on what "external" means, and what "Vue only" means. If you have control over the data, it's structure and it's location, you can do something like what @softbear has done - just import a javascript file inside your project. You can do it in numerous ways depending on your setup. His example consists of

<script src="images.js"></script>

which exports something along the lines of

window.images = [{ 'array of images': 'goes here'}]

If you're using Vue you should be able to use the bootstrapped project and just import this from your source files directly.

You can have a backend that provides the same result, and the browser will automatically load it when importing the script.

There are numerous ways but the result is the same. The most important thing here is that this file must declare your variable that should be used later on.


There are few problems with the approach on top: you don't have full control of when to start loading the data, nor when the data is loaded (there are ways to do that, but harder and pretty ugly); some cross domain serves don't allow you to execute js code directly - they can only provide data.

Which means that if you end up in this situation (like connecting to a dynamic set of data and not a hardcoded one), it's always better to make a request to load this data. Basically manually doing what the browser can do for you. But this way you have full (and easy) control of when and how this is done.

Again there are numerous ways - if you're using latest JS in a modern browser you can use the fetch API, or use some external tools like axios.

I would vote for the second approach, despite it might add another dependency to your project.

Sign up to request clarification or add additional context in comments.

1 Comment

Andrey, you're awesome! Thank you very much for the detailed response! This is working. To your explanation, I actually tried axios but I got a "Cross Origin Request Blocked" and it was also not working in some browsers so I wanted to simplify. I posted a question about the axios approach here: stackoverflow.com/questions/52461836/… There might be ways to solve that but the top solution you provided works for me for now. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.