Skip to content
Advertisement

Display lookup/relational data in a v-data-table with Vue and SQLServer

I created a Node App with Vue.js, Vuetify (Client side of app) and Express (Server side of App) and the data is stored in a SQL Server database (relational database).

Everything is up and running on my development machine and connection between client, server and database is working.

I just don’t know how to display “Lookup Data/relational data” in the tables that I am using.

3 tables of my database:

Relational tables

So I would like to display the Name fields of AssetMake and AssetModel INSTEAD of the FKAssetMake and FKAssetModel.

This is a screenshot of my table in the browser:

Table display

As you can see, the FK values are displayed but not the names.

The lookup tables and data to be displayed:

Lookup table data

Data object in chrome:

enter image description here

My Vue template:

<template>
  <div id="app">
    <v-app id="inspire">
      <v-card>
        <v-card-title>
          Asset (Vehicle/Vessel)
          <v-spacer></v-spacer>
          <v-text-field
            v-model="search"
            label="Search"
            append-icon="mdi-card-search-outline"
            single-line
            hide-details
          ></v-text-field>
        </v-card-title>

        <v-data-table dense
        :headers="headers"
        :items="assets"
        :search="search"
        sort-by="Name"
        class="elevation-1"
      >
        <template v-slot:top>
          <v-toolbar flat color="white">
            <v-toolbar-title>{{ tabelHeader }}</v-toolbar-title>

            <v-spacer></v-spacer>
            <v-dialog v-model="dialog" max-width="500px">
              <template v-slot:activator="{ on }">
                <v-btn color="primary" dark class="mb-2" v-on="on">New Item</v-btn>
              </template>
              <v-card>
                <v-card-title>
                  <span class="headline">{{ formTitle }}</span>
                </v-card-title>

                <v-card-text>
                  <v-container>
                    <v-row>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.Name" label="Name"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.FKMake" label="Make"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.FKModel" label="Model"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.Registration" label="Registration"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.Description" label="Description"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.Year" label="Year"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.Capacity" label="Capacity"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="4">
                        <v-text-field v-model="editedItem.isVessel" label="Is Vessel"></v-text-field>
                      </v-col>
                    </v-row>
                  </v-container>
                </v-card-text>

                <v-card-actions>
                  <v-spacer></v-spacer>
                  <v-btn color="blue darken-1" text @click="close">Cancel</v-btn>
                  <v-btn color="blue darken-1" text @click="save">Save</v-btn>
                </v-card-actions>
              </v-card>
            </v-dialog>
          </v-toolbar>
        </template>
        <template v-slot:item.Action="{ item }">
          <v-icon
            small
            class="mr-2"
            @click="editItem(item)"
          >
            edit
          </v-icon>
          <v-icon
            small
            @click="deleteItem(item)"
          >
            delete
          </v-icon>
        </template>
      </v-data-table>
      </v-card>
    </v-app>
  </div>
</template>

Script part:

<script>

import appConfig from '../config/appConfig.js'

const baseURL = "http://" + appConfig.server.ip + ":" + appConfig.server.port

export default {
  data: () => ({
    search: '',
    dialog: false,
    tabelHeader: '',
    assets: [],
    headers: [
      { text: 'Name', value: 'Name'},
      { text: 'Make', value: 'FKMake'},
      { text: 'Model', value: 'FKModel'},
      { text: 'Registration', value: 'Registration'},
      { text: 'Description', value: 'Description' },
      { text: 'Year', value: 'Year' },
      { text: 'Capacity', value: 'Capacity' },
      { text: 'Vessel', value: 'IsVessel' },
      { text: 'Actions', value: 'Action', sortable: false }
      ],

    editedIndex: -1,
    editedItem: {
      Name: '',
      FKMake: -1,
      FKModel: -1,
      Registration: null,
      Year: null,
      Capacity: null,
      Description: '',
      IsVessel: null
    },
    defaultItem: {
      Name: '',
      FKMake: -1,
      FKModel: -1,
      Registration: null,
      Year: null,
      Capacity: null,
      Description: '',
      IsVessel: null
    }
  }),

  watch: {
    dialog (val) {
      val || this.close()
    },
  },

  methods:{
    editItem (item) {
      this.editedIndex = this.assets.indexOf(item)
      this.editedItem = Object.assign({}, item)
      this.dialog = true
    },

    deleteItem (item) {
      const index = this.assets.indexOf(item)
      var isDelete = confirm('Are you sure you want to delete this item?')

      if (isDelete) {
        this.deleteAssetMake(item, index)
      }
    },

    close () {
      this.dialog = false
      setTimeout(() => {
        this.editedItem = Object.assign({}, this.defaultItem)
        this.editedIndex = -1
      }, 300)
    },

    save () {
      if (this.editedIndex > -1) {
        Object.assign(this.assets[this.editedIndex], this.editedItem)
        this.updateAssetMake(this.editedItem)
      } 
      else {
        this.assets.push(this.editedItem)
        this.addAssetMake(this.editedItem)
      }
      this.close()
    },



    deleteAssetMake (asset, index) {
      fetch(baseURL + '/api/asset/' + asset.ID, {
        method: 'DELETE'
        })
        .then(() => {
          this.assets.splice(index, 1)
          })
          },

    updateAssetMake (asset) {
      fetch(baseURL + '/api/asset/' + asset.ID, {
        body: JSON.stringify(asset),
        method: 'PUT',
        headers: {
        'Content-Type': 'application/json'
        }
      })
      .then(() => {

      })
    },

    addAssetMake (asset) {
      fetch(baseURL + '/api/asset/', {
        body: JSON.stringify(asset),
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        }
      })
    }
  },

  mounted () {
        fetch(baseURL + '/api/asset')
            .then(response => response.json())
            .then((data) => {
                this.assets = data.resultMessage
                console.log(data.resultMessage)
            })

            //.catch(() => console.log('Can’t access  response. Blocked by browser?'))
    },

    computed: {
    formTitle () {
      return this.editedIndex === -1 ? 'New Item' : 'Edit Item'
    },
  }
}
</script>
  1. How do I display the Name field of the referenced table instead of the Foreign Key.

  2. Is there a “better” way to accomplish the task with a “web type” database design?

Advertisement

Answer

@chans’s answer got me on the right track.

As the users will not be editing the data in the table ‘in-line”, one can change the query to show the data needed (AssetMake.Name and AsseteModel.Name).

I am using a dialog with a form to do the editing and adding of Assets. I then use a v-select to display the lookup data like this:

<v-col cols="12" sm="6" md="4">
  <v-select v-model="editedItem.FKModel" :items="assetModels" item-text="Name" item-value="ID" label="Model" autocomplete></v-select>
</v-col>

assetModels contains all asset models and was fetched from the database on mounted event.

Thanks to all who participated.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement