Search code examples
javascriptvue.jscodepen

How to Convert Codepen to Vue.js?


I'm having trouble moving this pen to Vue.js

This is what my code looks like for The Vue app - I understand where the HTML, and CSS should go. Should I add the Javascript to the individual component, or add it to the App.vue file?

What I want to do is test this code in a view I can route to.

This is the Javascript from the pen:

    var app = new Vue({
    el: '#app',
    mounted() {
        let vm = this
        axios
            .get(
                'https://sheets.googleapis.com/v4/spreadsheets/15qFEW97T-9Im9dx5G4KJqRorPDy74wwAvqaQm5Phz4w/values/A2%3AC12?key=AIzaSyBP4OwJmDCdX0rdOdgIa4q79g0XrMGcOSk'
            )
            .then(function (response) {
                let specials = response.data.values
                for (let index = 0; index < specials.length; index++) {
                    const element = specials[index]
                    let mitem = {
                        name: element[0],
                        description: element[1],
                        price: element[2]
                    }
                    if (vm.isEven(index)) {
                        vm.menuItems_L = vm.menuItems_L.concat(mitem)
                    } else {
                        vm.menuItems_R = vm.menuItems_R.concat(mitem)
                    }
                }
                console.log(response)
            })
    },
    data: {
        menuItems_L: [],
        menuItems_R: [],
        menuStyle: {
            background: '#ffe6d1',
            color: '#000'
        },
        dotStyle: {
            backgroundImage: 'radial-gradient(' + this.color + ' 1px, transparent 0px)'
        }
    },
    computed: {},
    methods: {
        isEven: function (n) {
            return n % 2 == 0
        }
    }
});

This is what my code looks like in the component (with changes from research / guessing), the HTML is in tags above it:

    <script>
    import axios from 'axios';

    export default {

    mounted() {
    let vm = this
    Vue.axios.get(
            'https://sheets.googleapis.com/v4/spreadsheets/15qFEW97T-9Im9dx5G4KJqRorPDy74wwAvqaQm5Phz4w/values/A2%3AC12?key=AIzaSyBP4OwJmDCdX0rdOdgIa4q79g0XrMGcOSk'
        )
        .then(function (response) {
            let specials = response.data.values
            for (let index = 0; index < specials.length; index++) {
                const element = specials[index]
                let mitem = {
                    name: element[0],
                    description: element[1],
                    price: element[2]
                }
                if (vm.isEven(index)) {
                    vm.menuItems_L = vm.menuItems_L.concat(mitem)
                } else {
                    vm.menuItems_R = vm.menuItems_R.concat(mitem)
                }
            }
            console.log(response)
        })
    },

    data: {
        menuItems_L: [],
        menuItems_R: [],
        menuStyle: {
            background: '#ffe6d1',
            color: '#000'
        },
        dotStyle: {
            backgroundImage: 'radial-gradient(#000, 1px, transparent 0px)'
        }
    },

    computed: {},

    methods: {
        isEven: function (n) {
            return n % 2 == 0
        },

        setColor: function (c) {
            c = menuStyle.color
            let colorStyle = 'radial-gradient(' + c + ' 1px, transparent 0px)'
            return colorStyle
        }
    }
}
</script>

Solution

  • You just need to remove the link on the first of the HTML templets, and make the <div id='#app'> is the root for the whole page as mentioned on [Vue Docs] 1

    Vue will show an error, explaining that every component must have a single root element. You can fix this error by wrapping the template in a parent element

    Also change data:{} to function data(){return{}} ... because As mentioned on Vue Docs, that Data have to be a function

    a component’s data option must be a function, so that each instance can maintain an independent copy of the returned data object:

    import axios from 'axios';
    
    export default {
        el: '#app',
        data() {
          return {
            menuItems_L: [],
            menuItems_R: [],
            menuStyle: {
                background: '#ffe6d1',
                color: '#000'
            },
            dotStyle: {
                backgroundImage: 'radial-gradient(' + this.color + ' 1px, transparent 0px)'
            }
          }
        },
        mounted() {
            let vm = this
            axios
                .get(
                    'https://sheets.googleapis.com/v4/spreadsheets/15qFEW97T-9Im9dx5G4KJqRorPDy74wwAvqaQm5Phz4w/values/A2%3AC12?key=AIzaSyBP4OwJmDCdX0rdOdgIa4q79g0XrMGcOSk'
                )
                .then(function (response) {
                    let specials = response.data.values
                    for (let index = 0; index < specials.length; index++) {
                        const element = specials[index]
                        let mitem = {
                            name: element[0],
                            description: element[1],
                            price: element[2]
                        }
                        if (vm.isEven(index)) {
                            vm.menuItems_L = vm.menuItems_L.concat(mitem)
                        } else {
                            vm.menuItems_R = vm.menuItems_R.concat(mitem)
                        }
                    }
                    console.log(response)
                })
        },
        methods: {
            isEven: function (n) {
                return n % 2 == 0
            }
        }
    }
    
    <template>
    <div id="app">
            <section id="specialssection" class="specials-container" v-if="menuItems_L" :style="menuStyle">
                <div id="special_component" :style="menuStyle">
                    <h1>Daily Specials</h1>
                    <div class="specials-table-container">
                        <table>
                            <tbody v-for="item in menuItems_L" :key="`specialmenu-${item.name}`">
                                <tr class="nameandprice">
                                    <td :style="dotStyle">
                                        <span :style="menuStyle">{{item.name}}</span>
                                    </td>
                                    <td :style="dotStyle">
                                        <span :style="menuStyle">${{item.price}}</span>
                                    </td>
                                </tr>
                                <tr class="description">
                                    <td colspan="2">{{item.description}}</td>
                                </tr>
                            </tbody>
                        </table>
                        <table>
                            <tbody v-for="item in menuItems_R" :key="`specialmenu-${item.name}`">
                                <tr class="nameandprice">
                                    <td :style="dotStyle">
                                        <span :style="menuStyle">{{item.name}}</span>
                                    </td>
                                    <td :style="dotStyle">
                                        <span :style="menuStyle">${{item.price}}</span>
                                    </td>
                                </tr>
                                <tr class="description">
                                    <td colspan="2">{{item.description}}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </section>
        </div>
    </template>