Primeng: [SimpleFeatureRequest]Add a Cell style function like row style function "rowStyleClass" in DataTable component.

Created on 26 Feb 2017  ·  15Comments  ·  Source: primefaces/primeng

I'm submitting a ... (check one with "x")

[ ] bug report => Search github for a similar issue or PR before submitting
[ X ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35

Current behavior

Current have a row style function "rowStyleClass", but not have a cell style function maybe like "cellStyleClass" and so on.

Expected behavior

add a cellStyleClass that :
"gets the row data and row index as parameters and returns a style class for the cell".
that function can return a style class to change cell background-color and so on.

Minimal reproduction of the problem with instructions

only add a cellStyleClass like rowStyleClass at the <td> element in datatable.ts 's line 162: TableBody compoment's template html. and add support function in the DataTable compoment like getRowStyleClass function.

What is the motivation / use case for changing the behavior?

example, change cell background-color to make a color-full timetable.
use div in template cannot fill the full cell.

Please tell us about your environment:

latest WebStorm

Language: [all | TypeScript X.X | ES6/7 | ES5]
all

pending-review

Most helpful comment

I have found a way to change background the color of the column.
Please let me know if I have done it the correct way or need some improvement.
Below is my code :

HTML Code:

<p-column  header="ID" >
    <template let-data="rowData" pTemplate="body">
            <span #x> {{ getColor(x,data) }} {{ data.id }}</span>
    </template>
</p-column>

TS Code:

// just a sample code, to assign background color depending on our required criteria
getColor(x, data) {
    var color: string;
    if (data.status === 1) {
      color = 'lightgreen';
    } else if (data.status === 2) {
      color = 'lightblue';
    } 
    x.parentNode.parentNode.style.background = color; // x.parentNode.parentNode accesses the <td> element of table :)
  }

Here is the output:
bg_color_td

Hope this helps!!
Thanks

All 15 comments

i use follow hack directive to solution it, so, i think i dont need it now !!

import {Directive, ElementRef, OnInit, Renderer, Input, OnDestroy, Output, EventEmitter} from '@angular/core';
import * as _ from 'lodash';
import {ReplaySubject, Subscription} from "rxjs";

export type ParentFinderType = (startNode: Node) => Node|null;

@Directive({
    selector: '[ccParentsSetter]'
})
export class ParentsSetterDirective implements OnInit,OnDestroy {

    @Input('classObject') set classObject(value: {[className: string]: boolean}) {
        this.classObjectSubject.next(value);
    }

    @Input('styleObject') set styleObject(value: {[styleName: string]: string}) {
        this.styleObjectSubject.next(value);
    }

    @Input('attributeObject') set attributeObject(value: {[attributeName: string]: string}) {
        this.attributeObjectSubject.next(value);
    }

    @Input('customParentFinder') customParentFinder: ParentFinderType;
    @Input('customNode') customNode: Node;

    @Input() onClickParam: any;
    @Output('ccParentsSetterOnClick') onClick: EventEmitter<{param: any, $event: Event}> = new EventEmitter();
    private onClickListenUnhookFunc: Function|undefined;

    // cold Subject
    classObjectSubject: ReplaySubject<any> = new ReplaySubject();
    styleObjectSubject: ReplaySubject<any> = new ReplaySubject();
    attributeObjectSubject: ReplaySubject<any> = new ReplaySubject();
    classObjectSubjectSubscription: Subscription;
    styleObjectSubjectSubscription: Subscription;
    attributeObjectSubjectSubscription: Subscription;

    constructor(private elementRef: ElementRef,
                private renderer: Renderer) {
    }

    isInit = false;

    ngOnInit() {
        let node = null;
        if (this.customNode instanceof Node) {
            node = this.customNode;
        } else {
            if (_.isFunction(this.customParentFinder)) {
                node = this.customParentFinder(this.elementRef.nativeElement);
            } else {
                let parentFinder = (node: Node, level: number = 0): Node|null => {
                    return (node && level < 10) ? (
                            node.nodeName == "TD" ? node : parentFinder(node.parentNode, level + 1)
                        ) : null;
                };
                node = parentFinder(this.elementRef.nativeElement);
            }
        }
        if (node) {
            this.onClickListenUnhookFunc = this.renderer.listen(node, "click", ($event: Event) => {
                this.onClick.emit({param: this.onClickParam, $event: $event});
            });
            this.classObjectSubjectSubscription = this.classObjectSubject.subscribe(
                next => {
                    _.forIn(next, (v, k) => {
                        this.renderer.setElementClass(node, k, v);
                    });
                }
            );
            this.styleObjectSubjectSubscription = this.styleObjectSubject.subscribe(
                next => {
                    _.forIn(next, (v, k) => {
                        this.renderer.setElementStyle(node, k, v);
                    });
                }
            );
            this.attributeObjectSubjectSubscription = this.attributeObjectSubject.subscribe(
                next => {
                    _.forIn(next, (v, k) => {
                        this.renderer.setElementAttribute(node, k, v);
                    });
                }
            );
            this.isInit = true;
        }
        if (!node || !this.isInit) {
            console.error("ParentsSetterDirective cannot init.");
            console.error("ParentsSetterDirective maybe not work.");
        }
    }

    ngOnDestroy() {
        if (this.isInit) {
            this.classObjectSubjectSubscription.unsubscribe();
            this.styleObjectSubjectSubscription.unsubscribe();
            this.attributeObjectSubjectSubscription.unsubscribe();
            if (this.onClickListenUnhookFunc) {
                this.onClickListenUnhookFunc();
            }
        }
    }

}

use it as follow

    <p-dataTable>
        <p-column [field]="ld">
            <template let-col let-rd="rowData" let-ri="rowIndex" pTemplate="body">
                    <div
                         class="text-center"
                         ccParentsSetter
                         [classObject]="countStyleClass(rd,col,ri)"
                         (ccParentsSetterOnClick)="tdClick(rd,col,ri)"
                    >
                    </div>
            </template>
        </p-column>
    </p-dataTable>

close it, please :(

I have found a way to change background the color of the column.
Please let me know if I have done it the correct way or need some improvement.
Below is my code :

HTML Code:

<p-column  header="ID" >
    <template let-data="rowData" pTemplate="body">
            <span #x> {{ getColor(x,data) }} {{ data.id }}</span>
    </template>
</p-column>

TS Code:

// just a sample code, to assign background color depending on our required criteria
getColor(x, data) {
    var color: string;
    if (data.status === 1) {
      color = 'lightgreen';
    } else if (data.status === 2) {
      color = 'lightblue';
    } 
    x.parentNode.parentNode.style.background = color; // x.parentNode.parentNode accesses the <td> element of table :)
  }

Here is the output:
bg_color_td

Hope this helps!!
Thanks

@supriya2992 it's work well but i dont like it as ParentsSetterDirective way.
because this is a hack way and cannot work well when dom struct change.

Better to use column style and styleClass.

can you post an example using column style and styleClass that accomplishes the same results please

@gjenner
@cagataycivici
But if you need control every cell's color, the column style will not enough. Example to write a simple colorfull task table.

you stated "Better to use column style and styleClass, just looking for an example of @supriya2992 's solution in your suggested method

yea, I use the ParentsSetterDirective as long as 4 mouth. ㄟ( ▔, ▔ )ㄏ

@cagataycivici I use styleClass

<p-column field="ExpirationDate" header="Expiration Date" [sortable]="true" [styleClass]="checkStyleClass">

and in ts.

public checkStyleClass(item: Client){
...
}

but the function is not fired

@pantonis try to use

[styleClass]="checkStyleClass()"

I think this should be reopened, since the solution mentioned here is still just a hacky workaround and nobody could post a working solution with styleClass.

+1

I guess the issue isn't a "simple feature request" after all since the latest pull request got denied because of performance impacts when calling a function for every table cell.

See #4463.

@cagataycivici Would you please reopen this issue. I need more attention for this feature. As of now, I am still using the hacky workaround described above but I can't add a new feature request for my application (dynamically configurable columns) without losing colored cells (which are mandatory) because the workaround is based on angular template reference variables which are static only and can't be dynamic.

@denniseffing I think your question need a way to control any special table cell by the table compoment ref on parents compoment's TS code.

i think you need a way to get a cell by the coordinates of the cell and the table's ref.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mitosandov picture mitosandov  ·  3Comments

gatapia picture gatapia  ·  3Comments

jisqaqov picture jisqaqov  ·  3Comments

pchristou picture pchristou  ·  3Comments

papiroca-tm picture papiroca-tm  ·  3Comments