2

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;   
    }

}

1 Answer 1

1

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().

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

2 Comments

Thank you - I missed that. Is there any way to trigger a reactive event when the rows would change? With simple data objects, vue sets up an Observer on it - can I do the same for a function?
@JohnP Well, instead of a function, you could make it a property and then it would be automatically made reactive.

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.