5
votes

I have an expanding data table in my parent component and a child component inside the expanded row with a button. I would like to change the background color of the associated row when I click the button inside the child component. I'm not sure how to target the row to add the css class on event.

ScanGrid(parent):

    <template>
      <v-flex v-if="items.length === 0">
        <ScanAdd @selectBatch="showScan" />
      </v-flex>
      <v-card v-else class="ma-5">
        <v-card-text>
          <v-layout align-center>
            <v-data-table
              :headers="headers"
              :items="items"
              item-key="StorageName"
              show-expand
              single-expand
              :expanded="expanded"
              hide-default-footer
              @click:row="clickedRow"
            >
              <template
                @isDeleted="deleteRow"
                v-if="groupBy === 'barCode'"
                v-slot:expanded-item="{ item }"
              >
                <td :colspan="12">
                  <ScanGridCode :item="item" />
                </td>
              </template>
              <template v-else v-slot:expanded-item="{ item }">
                <td :colspan="12">
                  <ScanGridDef :item="item" />
                </td>
              </template>
            </v-data-table>
          </v-layout>
        </v-card-text>
      </v-card>
    </template>

    <script>
    import { API } from "@/api";
    import ScanAdd from "./ScanAdd";
    import ScanGridCode from "./ScanGridCode";
    import ScanGridDef from "./ScanGridDef";
    export default {
      name: "ScanGrid",
      props: {
        items: {
          type: Array,
          required: true
        }
      },
      components: {
        ScanGridCode,
        ScanGridDef,
        ScanAdd
      },
      methods: {
        deleteRow(value) {
          this.isDeleted = value;
        },
        showScan(value) {
          this.selectedId = value;
          this.addScanBatch(value);
          this.$emit("processingBatch", true);
          this.processingBatch = true;
        },
        async addScanBatch(Id) {
          const selectedItems = await API.getPhysicalInventoryBatch(Id);
          if (selectedItems.data.Id === this.selectedId) {
            this.items = selectedItems.data.Locations;
          }
        },
        clickedRow(value) {
          if (
            this.expanded.length &&
            this.expanded[0].StorageName == value.StorageName
          ) {
            this.expanded = [];
          } else {
            this.expanded = [];
            this.expanded.push(value);
          }
        }
      },
      data: () => ({
        isDeleted: false,
        groupBy: "barCode",
        expanded: [],
        items: [],
        toDelete: "",
        totalResults: 0,
        loading: true,
        headers: [
          {
            text: "Localisation",
            sortable: true,
            value: "StorageName",
            class: "large-column font-weight"
          },
          {
            text: "Paquets scannés",
            sortable: true,
            value: "ScannedProduct",
            class: "large-column font-weight"
          },
          {
            text: "Paquets entrants",
            sortable: true,
            value: "Incoming",
            class: "large-column font-weight"
          },
          {
            text: "Paquets sortants",
            sortable: true,
            value: "Outgoing",
            class: "large-column font-weight"
          },
          {
            text: "Paquets inconnus",
            sortable: true,
            value: "Unknown",
            class: "large-column font-weight"
          }
        ]
      })
    };
    </script>

ScanGridCode(child):

    <template>
      <div class="codeContainer">
        <div class="cancelLocation">
          <v-flex class="justify-center">
            <v-btn class="ma-5" large color="lowerCase" tile  @click="deleteLocation"
              >Annuler le dépôt de cette localisation</v-btn
            >
          </v-flex>
        </div>
      </div>
    </template>

    <script>
    export default {
      name: "ScanGridCode",
      props: {
        item: {
          type: Object,
          required: true
        }
      },
      methods: {
        deleteLocation() {
          this.item.IsDeleted = true;
          this.$emit("IsDeleted", true);
        }
      },
      data: () => ({
        IsDeleted: false,
        groupBy: 0,
        headersGroupCode: [
          {
            text: "Code barre",
            sortable: true,
            value: "SerialNumber",
            class: "large-column font-weight-light"
          },
          {
            text: "De",
            sortable: true,
            value: "FromLocation",
            class: "large-column font-weight-light"
          },
          {
            text: "Vers",
            sortable: true,
            value: "ToLocation",
            class: "large-column font-weight-light"
          }
        ]
      })
    };
    </script>

I use Vuetify 2.1.7 and Vue 2.6.10. When I click on the button I call deleteLocation function. I assume I need to $emit a value to my parent but after that I don't know how to target the tr to change its style.

2
Are you using Vuex?nbixler
Yes I am. Version 3.0.1Vincent Desrosiers

2 Answers

0
votes

Since you're using Vuex, I would suggest using some variable such as store.state.selectedRow to keep track of whether or not a row has been selected (or in cases where there are more than one row, which row has been selected). Then you can have a computed property myProperty = this.$store.state.selectedRow in your Vue component which will automatically reflect the single source of truth, and your conditional class can be bound to this myProperty. This means you don't need to worry about emitting on events.

0
votes

The approach to emitting the event is what should be done. So I am assuming you will emit from deleteLocation function. Since you need a custom styling on rows you need to add the items slot and add your logic there

<template v-slot:item="{ item, select}">
 <tr :class="key === coloredRow ? 'custom-highlight-row' : ''">

     <td :colspan="12">
    <ScanGridCode @changeColor="changeColor(key)" :item="item" />
    </td>
 //add this method to your script element
 changeColor(idx) {
      this.coloredRow = idx;
    }