John P
John P

Reputation: 1580

Custom data object with functions in VueJS

I'm trying to build a custom DataSource object as the data portion of a table component, however VueJS appears to be re-writing the object to make it reactive. The vue component can access the direct data values fine (i.e. this.dataSource.columns or this.dataSource.sort) however I can't call any of the functions in the object, and I can't (for example) use the dataSource.rows() function to retrieve the filtered/sorted row data. Can Vue only work with plan javascript data objects? Or is there a trick I can use to make this work?

I'd like to use the object in a table component like:

<table ref="bodyTable" class="table-body">
    <tbody>
        <tr v-for="row in dataSource.rows" >
            <td v-for="column in dataSource.columns">{{row[column.name]}}</td>
        </tr>
    </tbody>
</table>

However vue can't seem to use the dataSource.rows function, or call any of the other methods in the object.

function RealtimeDataStore(columns,data,sort,filter){
    this.columns = columns;
    this._data = data;
    this.sort = sort;
    this.filter = filter;
    this.keyField = findKeyColumn();
    function updateData(data){
        //TODO: merge or insert the data into the this._data array
        //TODO: let parent component know data changed
    }
    function findKeyColumn(){
        for(var i=0;i<columns.length;i++){
            if(columns[i].isKey) return column[i].name;
        }
        return null;
    }
    function setSort(sortData){
        //TODO: verify sortData is in correct format and all columns are found
        this.sort = sortData;
        //TODO: let the component know data may have changed
    }
    function setFilter(filterData){
        //TODO: verify filterData is in correct format and all columns are found
        this.filter = filterData;
        //TODO: Let the component know data may have changed
    }
    function rows(){
        //TODO: filter data if needed
        //TODO: sort data if needed
        return this._data;   
    }

}

Upvotes: 2

Views: 4077

Answers (1)

Bert
Bert

Reputation: 82469

Typically, yes, it's best to stick with plain javascript objects for data in Vue.

However, in this case that is not why the code doesn't work.

First, rows is declared inside the scope of the RealtimeDataStore and is not accessible outside it. Second, the code doesn't call it as a function. row in dataSource.rows should be row in dataSource.rows().

Here is an example of how you might get the code to work.

console.clear()

function DataSource(){
    this.rows = function(){
      return [1,2,3]
    }
}

new Vue({
  el: "#app",
  data:{
    source: new DataSource()
  }
})
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
  <div v-for="row in source.rows()">
    {{row}}
  </div>
</div>

Notice that rows is exposed as a function on the object returned as a result of new DataSource().

Upvotes: 1

Related Questions