How to use data from apollo-client as data-source of QTable?
-
After switching from static data to the result of an apollo-client query I got the following error:
TypeError: "can't define property "__index": Object is not extensible" rows QTable.js:101 computedData QTable.js:100 VueJS 3 computedRowsNumber QTable.js:140 VueJS 3 pagesNumber table-pagination.js:52 VueJS 9
TypeError: "can't define property "__index": Object is not extensible" rows QTable.js:101 computedData QTable.js:100 VueJS 3 computedRows QTable.js:136 VueJS 3 getTableBody table-body.js:30 getBody QTable.js:207 render QTable.js:179 VueJS 7
Working with a simple table and iterating over the result array works fine.
-
Found a solution:
- use a different variable for QTable data
- implement a “watch” on the result variable of apollo-client
- reset QTable data variable with an empty array
- iterate with forEach over the result variable of apollo-client in the watch function and push each item inside “value” to it’s counterpart in the QTable data variable
watch: { books () { this.tableData = [] this.books.forEach((value) => { this.tableData.push({ id: value.id, author: value.author, title: value.title }) }) } }
Is there a better solution?
-
How are you calling your data? Can you show the whole code of your component?
Scott
-
@s-molinari: Hi Scott, thank you for your quick reply.
Here ist the code of my component:<template> <div> <q-table :columns="columns" :data="tableData" row-key="id" selection="single" binary-state-sort dense /> </div> </template> <script> import gql from 'graphql-tag' const BOOKS = gql` query { books { nodeId id title author } } ` const BOOKS_SUBSCRIPTION = gql` subscription { listen (topic: "books") { relatedNode { ... on Book { nodeId id title author } } } } ` export default { name: 'BooksSubscribeToMore', apollo: { books: { query: BOOKS, subscribeToMore: { document: BOOKS_SUBSCRIPTION, updateQuery: (previousResult, { subscriptionData }) => { if (previousResult.books.find(book => book.id === subscriptionData.data.listen.relatedNode.id)) { return previousResult } return { books: [...previousResult.books, subscriptionData.data.listen.relatedNode] } } } } }, watch: { books () { this.tableData = [] this.books.forEach((value) => { this.tableData.push({ id: value.id, author: value.author, title: value.title }) }) } }, data () { return { columns: [ { name: 'id', label: 'ID', field: 'id', sortable: true, required: true }, { title: 'title', label: 'Title', field: 'title', align: 'left', sortable: true }, { name: 'author', label: 'Author', field: 'author', align: 'left', sortable: true } ], books: [], tableData: [] } } } </script>
-
Try just using books as your data (table data) directly.
Scott
-
This was my first approach resulting in the errors above.
After this I take a look at the structure of data (table data) and books. -
Here ist the original code:
<template> <div> <q-table :columns="columns" :data="books" row-key="id" selection="single" binary-state-sort dense /> </div> </template> <script> import gql from 'graphql-tag' const BOOKS = gql` query { books { nodeId id title author } } ` const BOOKS_SUBSCRIPTION = gql` subscription { listen (topic: "books") { relatedNode { ... on Book { nodeId id title author } } } } ` export default { name: 'BooksSubscribeToMore', apollo: { books: { query: BOOKS, subscribeToMore: { document: BOOKS_SUBSCRIPTION, updateQuery: (previousResult, { subscriptionData }) => { if (previousResult.books.find(book => book.id === subscriptionData.data.listen.relatedNode.id)) { return previousResult } return { books: [...previousResult.books, subscriptionData.data.listen.relatedNode] } } } } }, data () { return { columns: [ { name: 'id', label: 'ID', field: 'id', sortable: true, required: true }, { title: 'title', label: 'Title', field: 'title', align: 'left', sortable: true }, { name: 'author', label: 'Author', field: 'author', align: 'left', sortable: true } ], books: [] } } } </script>
The code with the watcher works fine but it doesn’t feel “smooth”.
-
If you inspect data (table data) after “linking” with QTable you’ll find some aditional things like getters, setters, etc. inside. To protect these additional things QTable seems to use Object.preventExtensions().
-
@SB my hguess is you’ll have to deepcopy the table data and thats the one you use for your apollo, re assigned that copy to the model that you gave to your q-table when it changes maybe with a watcher or computed props.