0

I am able to render json in my vue app from an endpoint '/v1/api/sse?raceId=1' but I cannot figure out how to make the json into a table. The json is rendering fine for me however I do not know how to take this json and form it into a table.

Here's what the json payload looks like:

{
  "raceId": 1,
  "driverId": "17",
  "lap": 2,
  "position": 19,
  "time": "01:49.3",
  "milliseconds": 109274,
  "driverRef": "webber",
  "forename": "Mark",
  "surname": "Webber",
  "dob": "27/08/1976",
  "nationality": "Australian",
  "url": "http://en.wikipedia.org/wiki/Mark_Webber"
}

Here's my app.vue file:

  <div id="app">
    <div>
      <div>
        <p>
          <label>URL:</label>
          <input type="text" v-model="url" placeholder="http://">
        </p>

        <p>
          <label>Format:</label>
          <select v-model="format">
            <option value="plain">Plain</option>
            <option value="json">JSON</option>
          </select>
        </p>

        <p>
          <label>
            <input type="checkbox" v-model="includeCredentials">
            Include credentials?
          </label>
        </p>

        <p>
          <button :disabled="url.length === 0" @click.prevent="connect">Connect</button>
          <button @click.prevent="disconnect">Disconnect</button>
          <button @click.prevent="clear">Clear</button>
        </p>
      </div>

      <handlers
        :handlers.sync="handlers"
      />
    </div>

    <div>
      <LogDisplay
        :logs="logs"
      />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { SSEClient } from 'vue-sse/types'
import Handlers from './components/Handlers.vue'
import LogDisplay from './components/LogDisplay.vue'
import { now } from './utils'

let client: SSEClient | null

export default Vue.extend({
  name: 'App',
  components: {
    Handlers,
    LogDisplay
  },
  data () {
    return {
      url: '/v1/api/sse?raceId=1',
      generateColumns: 'test',
      includeCredentials: false,
      format: 'json',
      handlers: [
        {
          event: 'message',
          color: '#60778e'
        }
      ],
      logs: [] as [string, string, string][]
    }
  },
  methods: {
    connect () {
      // try disconnecting, just in case
      this.disconnect()

      this.log(`[info] connecting to ${this.url}`, 'system')

      // create the client with the user's config
      client = this.$sse.create({
        url: this.url,
        includeCredentials: this.includeCredentials,
        format: this.format
      })

      // add the user's handlers
      this.handlers.forEach((h) => {
        client!.on(h.event, (data) => { // eslint-disable-line
          this.log(data, h.color)
        })
      })

      client!.on('error', () => { // eslint-disable-line
        this.log('[error] disconnected, automatically re-attempting connection', 'system')
      })

      // and finally -- try to connect!
      client!.connect() // eslint-disable-line
        .then(() => {
          this.log('[info] connected', 'system')
        })
        .catch(() => {
          this.log('[error] failed to connect', 'system')
        })
    },

    disconnect () {
      if (client) {
        client.disconnect()
        client = null
        this.log('[info] disconnected', 'system')
      }
    },

    clear () {
      this.logs = []
    },

    log (message: string, color: string) {
      this.logs.push([now(), message, color])
    }
  },
  beforeDestroy () {
    this.disconnect()
  }
})
</script>

<style>
html, body {
  margin: 0;
  padding: 0;
}

h2 {
  display: inline;
}

button, input, select {
  font: inherit;
}

#app {
  background: #dddddd;
  font-family: sans-serif;
  min-height: 100vh;
  position: relative;
}

@media(min-width: 768px) {
  #app {
    display: flex;
  }

  #app > div {
    padding: 1rem;
  }

  #app > div:first-child {
    text-align: left;
  }

  #app > div:last-child {
    flex: 1;
  }
}
</style>

And here's my index.html:

<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Realtime Betting - Formula 1 Racing</title>

  <!-- Custom fonts for this template -->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template -->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

  <!-- Custom styles for this page -->
  <link href="vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">

  <!-- PNotify -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pnotify/2.0.0/pnotify.core.min.css">

</head>
<body id="page-top">

  <!-- Page Wrapper -->
  <div id="wrapper">

    <!-- Sidebar -->
    <ul class="navbar-nav bg-danger sidebar sidebar-dark accordion" id="accordionSidebar">

      <!-- Sidebar - Brand -->
      <a class="sidebar-brand d-flex align-items-center justify-content-center" href="">
        <div class="sidebar-brand-icon rotate-n-15">
          <i class="fa fa-flag-checkered"></i>
          <!-- <img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/F1.svg/1280px-F1.svg.png" alt=""> -->
        </div>
        <div class="sidebar-brand-text mx-3">Formula 1</div>
      </a>

      <!-- Divider -->
      <hr class="sidebar-divider my-0">

      <!-- Nav Item - Dashboard -->
      <!-- <li class="nav-item">
        <a class="nav-link" href="/">
          <i class="fas fa-fw fa-tachometer-alt"></i>
          <span>Dashboard</span></a>
      </li> -->

      <!-- Divider -->
      <!-- <hr class="sidebar-divider"> -->

      <br />

      <!-- Heading -->
      <div class="sidebar-heading">
        Data
      </div>

      <!-- Nav Item - Charts -->
      <li v-for="endpoint in this.endpoints" class="nav-item">
        <!-- <a class="nav-link" href="charts.html"> -->
        <a class="nav-link" :href="endpoint.name.toLowerCase()">
          <i class="fas fa-fw fa-chart-area"></i>
          <span>{{ endpoint.name }}</span></a>
      </li>


    </ul>
    <!-- End of Sidebar -->

    <!-- Content Wrapper -->
    <div id="content-wrapper" class="d-flex flex-column">

      <!-- Main Content -->
      <div id="content">

        <!-- Topbar -->
        <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">

          <!-- Sidebar Toggle (Topbar) -->
          <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
            <i class="fa fa-bars"></i>
          </button>

          <!-- Topbar Search -->
          <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
            <div class="input-group">
              <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
              <div class="input-group-append">
                <button class="btn btn-danger" type="button">
                  <i class="fas fa-search fa-sm"></i>
                </button>
              </div>
            </div>
          </form>

          <!-- Topbar Navbar -->
          <ul class="navbar-nav ml-auto">

            <!-- Nav Item - Search Dropdown (Visible Only XS) -->
            <li class="nav-item dropdown no-arrow d-sm-none">
              <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-search fa-fw"></i>
              </a>
              <!-- Dropdown - Messages -->
              <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
                <form class="form-inline mr-auto w-100 navbar-search">
                  <div class="input-group">
                    <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
                    <div class="input-group-append">
                      <button class="btn btn-primary" type="button">
                        <i class="fas fa-search fa-sm"></i>
                      </button>
                    </div>
                  </div>
                </form>
              </div>
            </li>

            <!-- Nav Item - Alerts -->
            <li class="nav-item dropdown no-arrow mx-1">
              <a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-bell fa-fw"></i>
                <!-- Counter - Alerts -->
                <span class="badge badge-danger badge-counter">3+</span>
              </a>
              <!-- Dropdown - Alerts -->
              <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown">
                <h6 class="dropdown-header">
                  Alerts Center
                </h6>
                <a class="dropdown-item d-flex align-items-center" href="#">
                  <div class="mr-3">
                    <div class="icon-circle bg-primary">
                      <i class="fas fa-file-alt text-white"></i>
                    </div>
                  </div>
                  <div>
                    <div class="small text-gray-500">December 12, 2019</div>
                    <span class="font-weight-bold">A new monthly report is ready to download!</span>
                  </div>
                </a>
                <a class="dropdown-item d-flex align-items-center" href="#">
                  <div class="mr-3">
                    <div class="icon-circle bg-success">
                      <i class="fas fa-donate text-white"></i>
                    </div>
                  </div>
                  <div>
                    <div class="small text-gray-500">December 7, 2019</div>
                    $290.29 has been deposited into your account!
                  </div>
                </a>
                <a class="dropdown-item d-flex align-items-center" href="#">
                  <div class="mr-3">
                    <div class="icon-circle bg-warning">
                      <i class="fas fa-exclamation-triangle text-white"></i>
                    </div>
                  </div>
                  <div>
                    <div class="small text-gray-500">December 2, 2019</div>
                    Spending Alert: We've noticed unusually high spending for your account.
                  </div>
                </a>
                <a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
              </div>
            </li>


              <!-- Dropdown - User Information -->
              <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
                <a class="dropdown-item" href="#">
                  <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
                  Profile
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
                  Settings
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
                  Activity Log
                </a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
                  <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
                  Logout
                </a>
              </div>
            </li>

          </ul>

        </nav>
        <!-- End of Topbar -->

        <!-- Begin Page Content -->
        <div class="container-fluid">

          <!-- Page Heading -->
          <h1 class="h8 mb-2 text-gray-800">Realtime Betting - Raw Racecar Feed</h1>
          <p class="mb-2">Code adapted from original repo here: <a target="_blank" href="https://github.com/Darrellrp/Formula-1-App">GitHub</a></p>

          <!-- DataTales Example -->
          <div id="table" class="card shadow mb-4">
            <div class="card-header py-3">
              <h6 class="m-0 font-weight-bold text-danger">RACERS</h6>
            </div>
            <div class="card-body">
              <div class="table-responsive">
                <div id="app"></div>
                <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">

                </table>
              </div>
            </div>
          </div>

        </div>
        <!-- /.container-fluid -->

      </div>
      <!-- End of Main Content -->

      <!-- Footer -->
      <footer class="sticky-footer bg-white">
        <div class="container my-auto">
          <div class="copyright text-center my-auto">
            <span><a target="_blank" href="https://github.com/Darrellrp/Formula-1-App">Darrellrp/Formula-1-App</a></span>
          </div>
        </div>
      </footer>
      <!-- End of Footer -->

    </div>
    <!-- End of Content Wrapper -->

  </div>
  <!-- End of Page Wrapper -->

  <!-- Scroll to Top Button-->
  <a class="scroll-to-top rounded" href="#page-top">
    <i class="fas fa-angle-up"></i>
  </a>

  <!-- Logout Modal-->
  <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
          <button class="close" type="button" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
        <div class="modal-footer">
          <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
          <a class="btn btn-primary" href="login.html">Logout</a>
        </div>
      </div>
    </div>
  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

  <!-- Page level custom scripts -->


  <!-- Vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

  <!-- Axios -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/aspnet-signalr/1.1.4/signalr.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pnotify/2.0.0/pnotify.core.min.js"></script>


  <script src="js/components/sidebar.js"></script>
  <script src="js/components/table.js"></script>

  <!-- Page level plugins -->
  <script src="vendor/datatables/jquery.dataTables.min.js"></script>
  <script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>

</body>

</html>

And finally the relevant component file:

  <div id="logs" ref="logs">
    <div
      v-for="(l, i) in logs"
      :key="i"
      :style="{ color: l[2], fontStyle: l[2] === 'system' ? 'italic' : 'normal' }"
    >
      <time>{{ l[0] }}</time>&gt;
      <span>{{ l[1] }}</span>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'LogDisplay',
  props: {
    logs: {
      required: true,
      type: Array
    }
  },
  watch: {
    logs () {
      this.$nextTick(() => {
        const el = this.$refs.logs as Element
        el.scrollTop = el.scrollHeight
      })
    }
  }
})
</script>

<style>
#logs {
  background: #444831;
  border-radius: 0.25rem;
  color: #e7e6e1;
  height: calc(100vh - 4rem);
  overflow-y: scroll;
  padding: 1rem;
}

#logs > div {
  padding-bottom: 0.5em;
}

#logs time {
  font-weight: bold;
  padding-right: 0.5em;
}

#logs span {
  padding-left: 0.5em;
}
</style>
1
  • The table inside your template renders nothing: <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"></table>. It is just an empty table. None of your posted code writes to it as far as I can see. You use jQuery and Vue and datatables.. do any of them write the table? Also you have <div id="app"></div> above the table.. is the table created by Vue components? Probably cannot do it outside the app. Commented Aug 4, 2021 at 7:40

1 Answer 1

1

Since you are getting a response, it is clear you are not really having a problem. Maybe you just do not understand how to consume your data. Let's say you are saving the response in a data variable called person and you need only the surname, you will use {{ person.surname }} to get that. In case of a list collection, you will follow step but will need a v-for. Check https://v2.vuejs.org/v2/guide/list.html for details.

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

Comments

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.