Create a fully dynamic table in EmberJS










2














I have defined a model in EmberJS with the following attributes:



import DS from 'ember-data';

export default DS.Model.extend(
"name": DS.attr('string'),
"status": DS.attr('string'),
"email1": DS.attr('string'),
"account_name": DS.attr('string'),
"phone_work": DS.attr('string'),
"date_entered": DS.attr('string'),
"date_modified": DS.attr('string')
);


I am creating a component called fields-list that would render these attributes into a table (headers, body; just like a typical table to list some fields). However, instead of making the table bound to this model only, I want to make the component fully dynamic, so that other models with different field names could also reuse this component to generate their tables as well.



This way, whenever the component is used, it detects the model and populates the headers of the table as well as the body according to the fields in that model.



How do I achieve this? If there is anything that's not clear in the query please do let me know, I've tried my best to explain the issue properly as much as I can. Thanks in advance!










share|improve this question





















  • Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
    – jelhan
    Nov 12 at 8:16










  • what have you tried so far and what is your problem? Have a look at eachAttribute.
    – Lux
    Nov 12 at 8:47










  • I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
    – noobdev
    Nov 12 at 9:30
















2














I have defined a model in EmberJS with the following attributes:



import DS from 'ember-data';

export default DS.Model.extend(
"name": DS.attr('string'),
"status": DS.attr('string'),
"email1": DS.attr('string'),
"account_name": DS.attr('string'),
"phone_work": DS.attr('string'),
"date_entered": DS.attr('string'),
"date_modified": DS.attr('string')
);


I am creating a component called fields-list that would render these attributes into a table (headers, body; just like a typical table to list some fields). However, instead of making the table bound to this model only, I want to make the component fully dynamic, so that other models with different field names could also reuse this component to generate their tables as well.



This way, whenever the component is used, it detects the model and populates the headers of the table as well as the body according to the fields in that model.



How do I achieve this? If there is anything that's not clear in the query please do let me know, I've tried my best to explain the issue properly as much as I can. Thanks in advance!










share|improve this question





















  • Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
    – jelhan
    Nov 12 at 8:16










  • what have you tried so far and what is your problem? Have a look at eachAttribute.
    – Lux
    Nov 12 at 8:47










  • I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
    – noobdev
    Nov 12 at 9:30














2












2








2







I have defined a model in EmberJS with the following attributes:



import DS from 'ember-data';

export default DS.Model.extend(
"name": DS.attr('string'),
"status": DS.attr('string'),
"email1": DS.attr('string'),
"account_name": DS.attr('string'),
"phone_work": DS.attr('string'),
"date_entered": DS.attr('string'),
"date_modified": DS.attr('string')
);


I am creating a component called fields-list that would render these attributes into a table (headers, body; just like a typical table to list some fields). However, instead of making the table bound to this model only, I want to make the component fully dynamic, so that other models with different field names could also reuse this component to generate their tables as well.



This way, whenever the component is used, it detects the model and populates the headers of the table as well as the body according to the fields in that model.



How do I achieve this? If there is anything that's not clear in the query please do let me know, I've tried my best to explain the issue properly as much as I can. Thanks in advance!










share|improve this question













I have defined a model in EmberJS with the following attributes:



import DS from 'ember-data';

export default DS.Model.extend(
"name": DS.attr('string'),
"status": DS.attr('string'),
"email1": DS.attr('string'),
"account_name": DS.attr('string'),
"phone_work": DS.attr('string'),
"date_entered": DS.attr('string'),
"date_modified": DS.attr('string')
);


I am creating a component called fields-list that would render these attributes into a table (headers, body; just like a typical table to list some fields). However, instead of making the table bound to this model only, I want to make the component fully dynamic, so that other models with different field names could also reuse this component to generate their tables as well.



This way, whenever the component is used, it detects the model and populates the headers of the table as well as the body according to the fields in that model.



How do I achieve this? If there is anything that's not clear in the query please do let me know, I've tried my best to explain the issue properly as much as I can. Thanks in advance!







javascript ember.js






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 at 8:08









noobdev

506




506











  • Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
    – jelhan
    Nov 12 at 8:16










  • what have you tried so far and what is your problem? Have a look at eachAttribute.
    – Lux
    Nov 12 at 8:47










  • I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
    – noobdev
    Nov 12 at 9:30

















  • Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
    – jelhan
    Nov 12 at 8:16










  • what have you tried so far and what is your problem? Have a look at eachAttribute.
    – Lux
    Nov 12 at 8:47










  • I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
    – noobdev
    Nov 12 at 9:30
















Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
– jelhan
Nov 12 at 8:16




Did you had a look on existing table implementations? There are a lot ember addons trying to achieve exactly what you want: emberobserver.com/categories/lists-and-tables
– jelhan
Nov 12 at 8:16












what have you tried so far and what is your problem? Have a look at eachAttribute.
– Lux
Nov 12 at 8:47




what have you tried so far and what is your problem? Have a look at eachAttribute.
– Lux
Nov 12 at 8:47












I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
– noobdev
Nov 12 at 9:30





I have looked at ember contextual table and ember light table . Ember Light Table has better documentation but I do not understand how to add table headers and data from the model dynamically.
– noobdev
Nov 12 at 9:30













2 Answers
2






active

oldest

votes


















1














I don't personally use Ember Data, so there might be better ways to do what you're doing, but I got a solution for you available as an ember twiddle or as a gist. This is nothing more than a proof of concept.



Let's break the question down really fast. You want to create a component that can take any model and magically build a table for you. At the highest level, we know that we need to be able to iterate over the data model's definition and create columns of specific types based off of the Ember Data types you've passed as DS.attr. Thinking further, we know Ember Data must have some sort of ability to do the same: eachAttribute. If it's a private API, recognize this is brittle and version specific (aka write tests).



So, given a model Foo:



import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend(
"name": attr('string'),
"status": attr('string')
);


Let's get the model's definition via the constructor:



var record = this.store.createRecord('foo', 
name: "model1",
status: "status1"
);
this.modelClass = record.constructor;


Ember light table takes a columns definition object which we can create dynamically from within our component through the use of eachAttribute on said model class:



columns: computed('modelClass', function() 
let modelClass = this.modelClass;
if(!modelClass) return
let columns = ;
modelClass.eachAttribute(function(key, meta)
columns.push(
label: key,
valuePath: key
);
);
return columns;
)


it's here that you could inspect the meta parameter of the eachAttribute function for the specific type of each attribute to set the cellComponent property within the column definition should you want to render different cell types.



There's a project called Ember Admin that builds up a CRUD interface automagically off of your data model so there's a place of inspiration.






share|improve this answer




















  • Thanks! the explanation and twiddle really helped with understanding the concept.
    – noobdev
    Nov 13 at 6:05


















1














Why resort to addons if you can just build this yourself?



app/templates/some-route.hbs



<FieldsList
@resources=users
@columns='id, firstName, lastName, job.title, job.company.name'
@sortBy='firstNameAsc'
@filterBy='firstName, lastName'
/>


app/components/fields-list/component.js



import Component from '@ember/component';
import computed from '@ember/object';

export default Component.extend(
classNames: ['fields-list'],

// Splits the string of keys into an array
columnMap: computed(function()
return this.columns.replace(/ /g, '').split(/,/g);
)
);


app/components/fields-list/template.hbs



<ul>

<li>
column
<span>get resource key</span>
/each
</li>
else
<li>No humans found</li>
/each
</ul>


app/components/fields-list/style.scss



.fields-list 
li
display: flex;
span
flex: 1;





Done in ember-cli: 3.5.0






share|improve this answer


















  • 1




    Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
    – noobdev
    Nov 13 at 6:07










  • Good spot, resolved :+1:
    – Jan Werkhoven
    Nov 13 at 11:34










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53258042%2fcreate-a-fully-dynamic-table-in-emberjs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














I don't personally use Ember Data, so there might be better ways to do what you're doing, but I got a solution for you available as an ember twiddle or as a gist. This is nothing more than a proof of concept.



Let's break the question down really fast. You want to create a component that can take any model and magically build a table for you. At the highest level, we know that we need to be able to iterate over the data model's definition and create columns of specific types based off of the Ember Data types you've passed as DS.attr. Thinking further, we know Ember Data must have some sort of ability to do the same: eachAttribute. If it's a private API, recognize this is brittle and version specific (aka write tests).



So, given a model Foo:



import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend(
"name": attr('string'),
"status": attr('string')
);


Let's get the model's definition via the constructor:



var record = this.store.createRecord('foo', 
name: "model1",
status: "status1"
);
this.modelClass = record.constructor;


Ember light table takes a columns definition object which we can create dynamically from within our component through the use of eachAttribute on said model class:



columns: computed('modelClass', function() 
let modelClass = this.modelClass;
if(!modelClass) return
let columns = ;
modelClass.eachAttribute(function(key, meta)
columns.push(
label: key,
valuePath: key
);
);
return columns;
)


it's here that you could inspect the meta parameter of the eachAttribute function for the specific type of each attribute to set the cellComponent property within the column definition should you want to render different cell types.



There's a project called Ember Admin that builds up a CRUD interface automagically off of your data model so there's a place of inspiration.






share|improve this answer




















  • Thanks! the explanation and twiddle really helped with understanding the concept.
    – noobdev
    Nov 13 at 6:05















1














I don't personally use Ember Data, so there might be better ways to do what you're doing, but I got a solution for you available as an ember twiddle or as a gist. This is nothing more than a proof of concept.



Let's break the question down really fast. You want to create a component that can take any model and magically build a table for you. At the highest level, we know that we need to be able to iterate over the data model's definition and create columns of specific types based off of the Ember Data types you've passed as DS.attr. Thinking further, we know Ember Data must have some sort of ability to do the same: eachAttribute. If it's a private API, recognize this is brittle and version specific (aka write tests).



So, given a model Foo:



import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend(
"name": attr('string'),
"status": attr('string')
);


Let's get the model's definition via the constructor:



var record = this.store.createRecord('foo', 
name: "model1",
status: "status1"
);
this.modelClass = record.constructor;


Ember light table takes a columns definition object which we can create dynamically from within our component through the use of eachAttribute on said model class:



columns: computed('modelClass', function() 
let modelClass = this.modelClass;
if(!modelClass) return
let columns = ;
modelClass.eachAttribute(function(key, meta)
columns.push(
label: key,
valuePath: key
);
);
return columns;
)


it's here that you could inspect the meta parameter of the eachAttribute function for the specific type of each attribute to set the cellComponent property within the column definition should you want to render different cell types.



There's a project called Ember Admin that builds up a CRUD interface automagically off of your data model so there's a place of inspiration.






share|improve this answer




















  • Thanks! the explanation and twiddle really helped with understanding the concept.
    – noobdev
    Nov 13 at 6:05













1












1








1






I don't personally use Ember Data, so there might be better ways to do what you're doing, but I got a solution for you available as an ember twiddle or as a gist. This is nothing more than a proof of concept.



Let's break the question down really fast. You want to create a component that can take any model and magically build a table for you. At the highest level, we know that we need to be able to iterate over the data model's definition and create columns of specific types based off of the Ember Data types you've passed as DS.attr. Thinking further, we know Ember Data must have some sort of ability to do the same: eachAttribute. If it's a private API, recognize this is brittle and version specific (aka write tests).



So, given a model Foo:



import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend(
"name": attr('string'),
"status": attr('string')
);


Let's get the model's definition via the constructor:



var record = this.store.createRecord('foo', 
name: "model1",
status: "status1"
);
this.modelClass = record.constructor;


Ember light table takes a columns definition object which we can create dynamically from within our component through the use of eachAttribute on said model class:



columns: computed('modelClass', function() 
let modelClass = this.modelClass;
if(!modelClass) return
let columns = ;
modelClass.eachAttribute(function(key, meta)
columns.push(
label: key,
valuePath: key
);
);
return columns;
)


it's here that you could inspect the meta parameter of the eachAttribute function for the specific type of each attribute to set the cellComponent property within the column definition should you want to render different cell types.



There's a project called Ember Admin that builds up a CRUD interface automagically off of your data model so there's a place of inspiration.






share|improve this answer












I don't personally use Ember Data, so there might be better ways to do what you're doing, but I got a solution for you available as an ember twiddle or as a gist. This is nothing more than a proof of concept.



Let's break the question down really fast. You want to create a component that can take any model and magically build a table for you. At the highest level, we know that we need to be able to iterate over the data model's definition and create columns of specific types based off of the Ember Data types you've passed as DS.attr. Thinking further, we know Ember Data must have some sort of ability to do the same: eachAttribute. If it's a private API, recognize this is brittle and version specific (aka write tests).



So, given a model Foo:



import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend(
"name": attr('string'),
"status": attr('string')
);


Let's get the model's definition via the constructor:



var record = this.store.createRecord('foo', 
name: "model1",
status: "status1"
);
this.modelClass = record.constructor;


Ember light table takes a columns definition object which we can create dynamically from within our component through the use of eachAttribute on said model class:



columns: computed('modelClass', function() 
let modelClass = this.modelClass;
if(!modelClass) return
let columns = ;
modelClass.eachAttribute(function(key, meta)
columns.push(
label: key,
valuePath: key
);
);
return columns;
)


it's here that you could inspect the meta parameter of the eachAttribute function for the specific type of each attribute to set the cellComponent property within the column definition should you want to render different cell types.



There's a project called Ember Admin that builds up a CRUD interface automagically off of your data model so there's a place of inspiration.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 12 at 10:52









mistahenry

5,26831829




5,26831829











  • Thanks! the explanation and twiddle really helped with understanding the concept.
    – noobdev
    Nov 13 at 6:05
















  • Thanks! the explanation and twiddle really helped with understanding the concept.
    – noobdev
    Nov 13 at 6:05















Thanks! the explanation and twiddle really helped with understanding the concept.
– noobdev
Nov 13 at 6:05




Thanks! the explanation and twiddle really helped with understanding the concept.
– noobdev
Nov 13 at 6:05













1














Why resort to addons if you can just build this yourself?



app/templates/some-route.hbs



<FieldsList
@resources=users
@columns='id, firstName, lastName, job.title, job.company.name'
@sortBy='firstNameAsc'
@filterBy='firstName, lastName'
/>


app/components/fields-list/component.js



import Component from '@ember/component';
import computed from '@ember/object';

export default Component.extend(
classNames: ['fields-list'],

// Splits the string of keys into an array
columnMap: computed(function()
return this.columns.replace(/ /g, '').split(/,/g);
)
);


app/components/fields-list/template.hbs



<ul>

<li>
column
<span>get resource key</span>
/each
</li>
else
<li>No humans found</li>
/each
</ul>


app/components/fields-list/style.scss



.fields-list 
li
display: flex;
span
flex: 1;





Done in ember-cli: 3.5.0






share|improve this answer


















  • 1




    Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
    – noobdev
    Nov 13 at 6:07










  • Good spot, resolved :+1:
    – Jan Werkhoven
    Nov 13 at 11:34















1














Why resort to addons if you can just build this yourself?



app/templates/some-route.hbs



<FieldsList
@resources=users
@columns='id, firstName, lastName, job.title, job.company.name'
@sortBy='firstNameAsc'
@filterBy='firstName, lastName'
/>


app/components/fields-list/component.js



import Component from '@ember/component';
import computed from '@ember/object';

export default Component.extend(
classNames: ['fields-list'],

// Splits the string of keys into an array
columnMap: computed(function()
return this.columns.replace(/ /g, '').split(/,/g);
)
);


app/components/fields-list/template.hbs



<ul>

<li>
column
<span>get resource key</span>
/each
</li>
else
<li>No humans found</li>
/each
</ul>


app/components/fields-list/style.scss



.fields-list 
li
display: flex;
span
flex: 1;





Done in ember-cli: 3.5.0






share|improve this answer


















  • 1




    Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
    – noobdev
    Nov 13 at 6:07










  • Good spot, resolved :+1:
    – Jan Werkhoven
    Nov 13 at 11:34













1












1








1






Why resort to addons if you can just build this yourself?



app/templates/some-route.hbs



<FieldsList
@resources=users
@columns='id, firstName, lastName, job.title, job.company.name'
@sortBy='firstNameAsc'
@filterBy='firstName, lastName'
/>


app/components/fields-list/component.js



import Component from '@ember/component';
import computed from '@ember/object';

export default Component.extend(
classNames: ['fields-list'],

// Splits the string of keys into an array
columnMap: computed(function()
return this.columns.replace(/ /g, '').split(/,/g);
)
);


app/components/fields-list/template.hbs



<ul>

<li>
column
<span>get resource key</span>
/each
</li>
else
<li>No humans found</li>
/each
</ul>


app/components/fields-list/style.scss



.fields-list 
li
display: flex;
span
flex: 1;





Done in ember-cli: 3.5.0






share|improve this answer














Why resort to addons if you can just build this yourself?



app/templates/some-route.hbs



<FieldsList
@resources=users
@columns='id, firstName, lastName, job.title, job.company.name'
@sortBy='firstNameAsc'
@filterBy='firstName, lastName'
/>


app/components/fields-list/component.js



import Component from '@ember/component';
import computed from '@ember/object';

export default Component.extend(
classNames: ['fields-list'],

// Splits the string of keys into an array
columnMap: computed(function()
return this.columns.replace(/ /g, '').split(/,/g);
)
);


app/components/fields-list/template.hbs



<ul>

<li>
column
<span>get resource key</span>
/each
</li>
else
<li>No humans found</li>
/each
</ul>


app/components/fields-list/style.scss



.fields-list 
li
display: flex;
span
flex: 1;





Done in ember-cli: 3.5.0







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 at 11:33

























answered Nov 12 at 11:15









Jan Werkhoven

1,5571325




1,5571325







  • 1




    Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
    – noobdev
    Nov 13 at 6:07










  • Good spot, resolved :+1:
    – Jan Werkhoven
    Nov 13 at 11:34












  • 1




    Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
    – noobdev
    Nov 13 at 6:07










  • Good spot, resolved :+1:
    – Jan Werkhoven
    Nov 13 at 11:34







1




1




Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
– noobdev
Nov 13 at 6:07




Interesting solution, although I think you may have swapped the second and third paths by accident. Nevertheless I understand where you're going with this. Thanks :)
– noobdev
Nov 13 at 6:07












Good spot, resolved :+1:
– Jan Werkhoven
Nov 13 at 11:34




Good spot, resolved :+1:
– Jan Werkhoven
Nov 13 at 11:34

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53258042%2fcreate-a-fully-dynamic-table-in-emberjs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3

Museum of Modern and Contemporary Art of Trento and Rovereto