简体   繁体   中英

Change Background Color on DIV Grid in Vue.js without Changing Other's Background

I can change the background color of an element in Vue using an @click event easily but I'm having trouble with a large grid changing the background color, in order, based on an array/object of states/colors.

I've tried binding the style and class to a data object but I wind up changing the whole grid at once instead of each individual element. I've been using Vue for a week or two now and I'm stuck on this. I will be attaching it to my Laravel API to pull in the days dynamically and basically use each grid element to switch the employee on, off, maybe, or null(unknown or undetermined). There will also be 3 small icons (booleans, on/off) in each corner of the grid elements to add additional parameters on whether they're pay is billable, how it's calculated and whether they are allowed OT.

<template>
    <div id="app">
        <heading class="mb-6">Scheduler</heading>
        <form>
            <div class="flex mb-4">
                <div class="bg-gray-400 w-1/3 h-12">
                    <label for="budgets">Select Budget</label><br>
                    <select class="form-control form-select mb-3 w-full" id="budgets" v-model="budgetSelect">
                        <option selected="selected" disabled>--</option>
                        <!-- start the budget select loop -->
                        <option v-for="(budget,index) in budgets" :key="index" :value="index">
                            {{ budget.name }} -- {{ budget.subject }}
                        </option>
                    </select>
                </div>
                <div class="bg-gray-400 w-1/3 h-12">
                    <label v-if="budgetSelect!=null" for="series">Select Series</label><br>
                    <select v-if="budgetSelect!=null" class="form-control form-select mb-4 w-full" v-model="seriesSelect" id="series">
                        <option selected="selected" disabled>Select a Series</option>
                        <!-- start the series select loop -->
                        <option v-for="(series,index) in seriesArray" :key="index">
                            {{ series.name }}
                        </option>
                    </select>
                </div>
                <div class="bg-gray-400 w-1/3 h-12">
                    <label v-if="seriesSelect!=null" for="events">Select Event</label><br>
                    <select v-if="seriesSelect!=null" class="form-control form-select mb-3 w-full" v-model="eventSelect" id="events">
                        <option selected="selected" disabled>Select an Event</option>
                        <!-- start the event select loop -->
                        <option v-for="(event,index) in events" :key="index">
                            {{ event.name }}
                        </option>
                    </select>
                </div>
            </div>
        </form>
        <div v-if="eventSelect!=null" class="p-4 flex">
            <h1 class="text-2x1">
                Week of June 16th, 2019
            </h1>
        </div>
        <!-- to conditionally hide this grid -->
        <!--  v-if="eventSelect!=null" -->
        <div class="flex justify-center">
            <div class="square-header">
                <div class="square-header-content"></div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Sunday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Monday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Tuesday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Wednesday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Thursday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Friday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Saturday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Sunday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Monday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Tuesday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Wednesday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Thursday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Friday</div>
            </div>
            <div class="square-header">
                <div class="square-header-content">Saturday</div>
            </div>
        </div>

<!-- start the rows -->
<!-- start the rows -->
<!-- start the rows -->

        <div v-for="index in 7" :key="index" class="flex justify-center">
            <div class="square">
                <div class="square-content" style="vertical-align:middle;">User </div>
            </div>
            <div v-for="index in 14" :key="index" 
                @click="changeDayState(dayCode,state,index)"
                class="square bg-danger">
                    <div class="square-content"></div>
            </div>
        </div>
    </div>

</template>
<script>
export default {
    data(){
        return {
            // main vars
            startDay: 'Sunday',
            weekSpan: 2,
            dayCode: [
                {key: 'on', value: '#21b978'},
                {key: 'off', value: '#e74444'},
                {key: 'maybe', value: '#ffeb3b'},
                {key: 'empty', value: 'var(--white-50)'}
            ],
            state: 'on',
            bgColor: {
                backgroundColor: ''
            },


            // attribute icon paramaters
            icons: {
                straightTime: {
                    placement: '',
                    url: ''
                },
                overTime: {
                    placement: '',
                    url: ''
                },
                billable: {
                    placement: '',
                    url: ''
                }
            },

            // begin budget drop down
            budgetSelect: null,
            budget: {
                id: "",
                name: "",
                subject: "",
            },
            budgets: [],

            // begin series drop down
            seriesSelect: null,
            series: {
                name:"",
            },
            seriesArray: [],

            // begin event drop down
            eventSelect: null,
            event: {
                name: "",
            },
            events: [],

            // begin day drop down
            daySelect: null,
            day: {
                scheduled_date: "",
                user:"",
            },
            days: [],

            uri: window.location.origin + '/clock-in',
            budgetURI: window.location.origin + '/api/scheduler',
            seriesURI: window.location.origin + '/api/scheduler/series/1',
            eventURI: window.location.origin + '/api/scheduler/events/1',
            dayURI: window.location.origin + '/api/scheduler/days/1',
        }
    },
    methods: {
        getBudgets(){
            axios.get(this.budgetURI).then(response=>{
                this.budgets = response.data.budgets;
                console.log(response.data.budgets);
            });
        },
        getSeries(){
            axios.get(this.seriesURI).then(response=>{
                this.seriesArray = response.data.series;
                console.log(response.data.series);
            });
        },
        getEvents(){
            axios.get(this.eventURI).then(response=>{
                this.events = response.data.events;
                console.log(response.data.events);
            });
        },
        getDays(){
            axios.get(this.dayURI).then(response=>{
                this.days = response.data.days;
                console.log(response.data.days);
            });
        },
    changeDayState(dayCode,key,index){
        for (var i = 0; i < dayCode.length; i++){
            if (dayCode[i].key === key){
            console.log(dayCode[i].key + " -- " + dayCode[i].value);
            this.state = dayCode[i + 1].key;
            this.bgColor.backgroundColor = dayCode[i + 1].value;
            return null;
            }else{
                this.state = "else";
            }
       }
    }

    },
    mounted(){
        this.getBudgets();
        this.getSeries();
        this.getEvents();
        this.getDays();
    }
}

</script>
<style>
.square-header {
    float: left;
    position: relative;
    width: 6%;
    height: 1.2em;
    margin: .15%;
    overflow: hidden;
    border-radius: 10px;
}
.square-header-content {
    position: absolute;
    height: 90%;
    width: 90%;
    padding: 5% 5%;
    text-align: center;
    bottom: 0;
    font-size: .8rem;
}

.square {
    float: left;
    position: relative;
    width: 6%;
    padding-bottom: 6%;
    margin: .15%;
    overflow: hidden;
    border-radius: 10px;
}
.square-content {
    position: absolute;
    height: 70%;
    width: 90%;
    padding: 15% 5%;
    text-align: right;
    bottom: 1px;
    font-size: .8rem;
    vertical-align: middle;
}
</style>

Particular focus is on the loop where the code comments say to start the rows. I've given the style to help with visualizing the grid. The function I'm trying to pull this off in is changeDayState(). I should be able to track each day and cycle through 4 states and background colors for each div.

This was solved by passing in the current element using $event into the method then manipulating it in the method. See below...

            <div v-for="parent_index in 7" :key="parent_index" class="flex justify-center">
                <div class="square">
                    <div class="square-content" style="vertical-align:middle;">User {{ parent_index }}</div>
                </div>
                <div v-for="index in 14" :key="index" class="square bg-success"
                    @click="changeDayState(dayCode,$event)">
                </div>
            </div>
        changeDayState: function (dayCode,$event){
            for (var i = 0; i < dayCode.length; i++){
                if($event.currentTarget.classList.contains(dayCode[i].value)){
                    console.log('tracking ' + dayCode[i].value + ' and now next is ' + dayCode[i+1].value);
                    $event.target.classList.toggle(dayCode[i].value);
                    $event.target.classList.toggle(dayCode[i+1].value);
                    i++; // this throws the loop off after setting the correct value
                }else if($event.currentTarget.classList.contains(dayCode[dayCode.length-1].value)){
                    console.log('we reached the end and are looking at ' + dayCode[i].value);
                    $event.target.classList.toggle(dayCode[i].value);
                    $event.target.classList.toggle(dayCode[dayCode.length-1].value);
                }
            }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM