miguelcobain / ember-yeti-table

Yeti Table

Home Page:https://miguelcobain.github.io/ember-yeti-table

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to force a reload of data from outside the table

hbrysiewicz opened this issue · comments

Might be a silly question, and maybe I missed it in the docs, but since the loadData method is getting passed some fun params from the table config in the template, is there a way to "force" this method to get fired with proper params again?

The scenario is there is an action column in the table that removes a record or moves it to a different page (status update, archived, etc).

I actually stumbled upon this same scenario yesterday.

The only way I could think to solve this would be something inspired by what ember-power-select does.
Basically we could have a @registerAPI action that would be called with an "api" object. This api object would contain actions and also other meta-information about the table. One of those actions could be a reloadTable, but you would also have the others nextPage, previousPage, etc.

It would look something like:

<YetiTable @registerAPI={{fn (mut this.tableAPI)}} ...>
  ...
</YetiTable>

Then, in your component/controller (or even on the template, you could call

addNewRecord() {
  // add the record using ember-data or whatever else
  this.tableApi.actions.reloadTable();
}

or even in the template

<button {{on "click" this.tableApi.actions.reloadTable}}>
  Reload table
</button>

This would also enable more complex scenarios where you want to control the table from outside the table component itself.

What do you think?

/cc @cah-briangantzler

I have not used the loadTable portion yet so not sure if there is a better way. I am familiar with the API concept and in fact you are kind doing that already with paginiation

actions=(hash
    previousPage=(fn this.previousPage)
    nextPage=(fn this.nextPage)
    goToPage=(fn this.goToPage)
    changePageSize=(fn this.changePageSize)
  )

Although these methods were meant to be passed onto to another component, not this component. However the API you are proposing would allow the parent component to actually do the buttons instead of requiring a full support component.

I am fine with this approach, just need to have a discussion of what is included in this api etc.

@miguelcobain this would definitely be helpful.

I found a work-around for handling actions from "inside" the table by passing table.rows.query and running another query to refresh the store. However, this does not work for adding rows from outside the table. I have a button outside the table to add a record, and then need a way to refresh again. So my work around is not complete.

After I posted this I realized that these actions could be passed to buttons on this component and it would not require a specialized support component, its basically what and how it should be accessed.

With the new render components, you can now also do this

<YetiTabel as |table|>
   <table.header {{did-insert this.saveAPI table}} as |header|>
   </table.header>
</YetiTable>

Which effectively saves the current API without doing the ref function (power-select did the api action long before render modifiers worked) and now you could call the next and previous actions. granted you also have access to table.row in the JS which is useless, so maybe it should be

<YetiTabel as |table info api|>
   <table.header 
          {{did-insert this.saveAPI api}} 
          {{did-insert this.saveInfo info}} 
          {{did-update this.saveInfo info}} 
     as |header|>
   </table.header>
</YetiTable>

Where table would contain all the components and things meant only for the template and api would contain just actions. info would contain things like filtered rows, counts , etc. Things that might update.

I guess its up to you as to if you supply the action to get a reference to the API or more organize the current API and let the user use the render modifiers to do what they will with them

@cah-briangantzler I'm not sure how this works for a scenario where the action that modifies the items in the table happens from outside the context of the table. For instance:

/users shows an "Add user" button and then the YetiTable and then an {{outlet}}
The table never re-renders or re-inserts when the child route /users/new is loaded. /users/new creates a new user record and when ember returns to the /users route nothing re-renders.

Maybe there is a way but from what I know of the new render modifiers (which isn't much) I don't see a way.

it works the same. If yeti were to supply a reference action, it would look like this.

<YetiTable @onReferenceApi={{this.saveApi}} as |table|>
   <table.header as |header|>
   </table.header>
</YetiTable>

Its basically the same thing, just using did-insert to save the yielded item instead of a specific action supplied by the component.

Are you saying this functionality already exists or are we talking hypothetical?

With the new render components, you can now also do this

This line confused me as I thought you were saying this is supported by YetiTable?

@cah-briangantzler indeed, both options are functionally equivalent. I feel that the did-insert modifier one is a bit "hacky", because you're not actually interested in the header rendering at all.

It would feel less hacky with ember-render-helpers:

<YetiTable as |table|> 
  {{did-insert this.saveAPI table}}
  
  <table.header as |header|>
		...
</YetiTable>

They aren't part of ember yet, though.

You could also do the not render table and put it on the table component. I was not aware of that addon.

@hbrysiewicz Yes I was saying that is available now if the desired action was already being yeilded. Pagination type stuff is. Sadly what you are looking for is not.

I was giving @miguelcobain options as to how this could be implemented. Up to him which he chooses

Hey, just looking at this. Is the API also yielded under table? so if I have a button I could say {{ on "click" table.api.nextPage}}. otherwise I would need to create an action to save the api then refer to that variable in the HBS, that could male an otherwise template only component need to create a JS.

@cah-briangantzler table.actions is currently the exact same object as what is passed to @registerApi.
So you can do {{on "click" table.actions.nextPage}} like you already could, and now you could also have {{on "click" table.api.reloadData}}.

We might want to expand the registerApi object to contain more things in the future, but I think this is a good start.