meteor-tabular
meteor-tabular copied to clipboard
Set columns by role
How can I set to Tabular.Table that I want to show more 2 colunms if I have administrator role?
I've already gone through... 5? Maybe more issues asking this same thing. And I'm still looking for a way to do it.
I've tried to use the visible option dinamically (this is, using a function to get that true/false value), but it seems to be called only when the meteor app starts, not when it's rendered so, no userId value at all.
Any ideas or just an straight statement that this can't be done?
I had same idea like you but din't work...something like this:
columns: [{
data: "name",
title: "Name",
className: "center aligned",
orderable: true,
visible:function(){
//If user set to see this columns returns true else return false
}
}, {
data: "ultimaPosicao.id",
title: "ID",
className: "center aligned",
orderable: false,
visible:function(){
//If user set to see this columns returns true else return false
}
}];
I was doing the same but using a global función like this:
isAdmin = function() {
// returns true if user has admin roles (using alanning:roles)
}
so I would hace something like this un the tabular definition:
....
visible: isAdmin(),
...
No luck. A console.log in the isAdmin function shows up only on app startup, not when table is rendered :(
The only working solution I've found is having two different tabular table definitions (which sucks and is what I wanted to avoid) and according to user role, show one or another in the template using template helpers. As the columns I'm hidding are the same in all tables, I'm generating the second tabular definitions dinamically at startup time, but that's not the solution I'm looking for.
@aldeed Could you help us with this solution?
As also mentioned from me in the issue https://github.com/aldeed/meteor-tabular/issues/295 i would suggest you to make a server method which creates the tabular table on the server side and after that init the tabular table on the client side. important for this is, that the tabular on the client side is created AFTER the initalization on the server side.
I already us this kind of function. It would be nice if in future this would be automaticly made from the package. So that I could place the code of the tabular only the client-side and not in common code
@kevinpeter Please, Do you have any example code of this sugestion?
Here is a code example (I removed some code, which is used for personal. I hope it still works ;) ):
Server-Side
Meteor.methods({
defineTabularTable:function(name, collectionName, columns, extraFields, selector, publishName){
//Check if tabular already exists on server side
if(!_.isUndefined(TabularTables[name])) return;
var tableProperties = {
name: name,
collection: db[collectionName],
columns: columns
};
if(!_.isUndefined(publishName)) tableProperties.pub = publishName;
if(!_.isUndefined(publishName)) tableProperties.extraFields = extraFields;
if(!_.isObject(selector)) selector = {};
tableProperties.selector = function( userId ) {
//Here you can make global role and right checks
//if(!hasRights(userId)) return;
return selector;
};
TabularTables[name] = new Tabular.Table(tableProperties);
}
});
Client-Side Template
<template name="tabularTable">
{{initRenderStart}}
{{#if isReady}}
{{> tabular table=_tableData class="table table-condensed"}}
{{else}}
{{initPublish}}
<div >
<div class="col-sm-5"></div>
<div class="col-sm-1">
Loading ...
</div>
<div class="col-sm-5"></div>
</div>
{{/if}}
</template>
Client-Side JS
Template.tabularTable.helpers({
isReady:function(){
if(_.isUndefined(this._isReady)) this._isReady = new ReactiveVar(false);
return this._isReady.get();
},
initRenderStart:function(){
this._isReady = new ReactiveVar(false)
},
initPublish:function(){
Template.tabularTable.init(this, false);
},
_tableData: function() {
return Template.tabularTable.init(this, true);
},
});
Template.tabularTable.init = function(data, isPublishReady) {
var self = data;
var tabularConf = {
collection:self.collection,
selector:self.selector,
extraFields:self.extraFields,
columns:self.columns
}
var name = tabularConf.name + "_" + tabularConf.collection._collection.name + JSON.stringify(tabularConf.selector);
if(isDefined(TabularTables[name])) {
if(isUndefined(self._isReady)) self._isReady = new ReactiveVar(false);
self._isReady.set(true);
return TabularTables[name];
}
if(!isPublishReady) {
Meteor.call('defineTabularTable',
name,
tabularConf.collection._collection.name,
tabularConf.columns,
tabularConf.extraFields,
tabularConf.selector,
tabularConf.pub,
function(error) {
if(error) {
console.log(error);
}
else
{
self._isReady.set(true);
}
}
);
}
else
{
var tabularOptions = {
name : name,
extraFields : tableOptions.extraFields,
selector : function( userId ) {
return tabularConf.selector;
},
collection : tabularConf.collection,
columns : tabularConf.columns,
responsive: true,
autoWidth: false,
throttleRefresh: 5000
};
if (!_.isUndefined(self.tabularConf.pub)) tabularOptions.pub = tabularConf.pub;
if(!_.isUndefined(name)) {
TabularTables[name] = new Tabular.Table(tabularOptions);
return TabularTables[name];
}
else
{
return new Tabular.Table(tabularOptions);
}
}
}
And you should now call the template like following:
<template name="test">
{{> tabularTable name="myTabularTableTest"
collection=collection
selector=selector
extraFields=extraFields
columns=columns
}}
</template>
And if you want to show a column depending on the user role, you could modify the Server-Method defineTabularTable and the Client-Function Template.tabularTable.initto show or hide a column.
Sounds great @kevinpeter , I'll give it a try. Thanks! :)
@kevinpeter how did you defined db variable?
Exception while invoking method 'defineTabularTable' ReferenceError: db is not defined
Its an object. where each collection is saved. For examle:
db = {};
db.tasks = new Mongo.Collection('tasks');
I will try to make a repo with a demo on the comming weekend for helping you.
@kevinpeter It will be awesome! Waiting for this repo! Thank you so much!
@kevinpeter In my case I do not use object to store collection instante...just use global variable like this:
Tasks = new Mongo.Collection('tasks');
@kevinpeter You could make the repository with example for us?
@luixal You could get something through the example? Could you share with me?
I will publish the example tomorrow evening. Until now, I did not found time to implement the examples.
@kevinpeter thank you so much!
Hi @felipesmendes , I finally went with something like this on the initComplete tabular field:
initComplete: function (settings, json) {
// calls a function for hidding columns according to indexes AFTER table has been init on client:
hideTableColumns(this, [0, 9, 10, 11]);
},
this is the implementation for the hideTableColumns function:
// hides columns for indexes on the provided tabular table:
hideTableColumns = function(table, columnsToHide) {
// this line is here only for admin users to see all columns:
if (Meteor.user() && Roles.userIsInRole(Meteor.user()._id, 'admin')) return;
// here goes the hidding:
var dt = table.DataTable();
columnsToHide.map(function(columnIndex) {
dt.column(columnIndex).visible(false);
});
};
Not the best solution, but works pretty well :)
Awesome man! I'll try!
I, you and @kevinpeter can improve the project documentation or implement the best way to do this in the package and create a pull request.
What do you think?
Other structure problem that I have is all tabular table definition is in one file in the root folder of project and I want to separate then in many files for any report that I have.
How do you do that?
@felipesmendes sorry man, didn't read this until now (same on me) :(
As Tabular is a really big project, I don't fell confident enough to get into the code because probably, someone else knows the project better to implemente something like this.
Also, I'm having trouble with responsiveness (DataTables problem in fact) so maybe I have to move on to another solution for displaying collection.