Primeng datatable cell background color change - primeng

Need to change <td> background color if user change the value from dropdown.
<p-column field="newValue" header="User new value" >
<template let-col let-list="rowData" pTemplate="body">
// dropdown here
</template>
</p-column>

It's working fine for me. '#dropdownId' is dynamic. I am using angular2.
let td = this.element.nativeElement.querySelector('#dropdownId').parentNode.parentNode;
this.renderer.setElementStyle(td, 'background-color', 'blue');

Related

Allow only one checkbox to be checked on b-table bootstrap vue

I have a column of checkboxes on a b-table but I only want the user to be able to select one. Selecting another should uncheck the first option.
I tried to set selected = [] and refresh the table upon selection of a second checkbox but while the selected object ends up with the correct row data, the checkbox still appears on the table.
I also tried to call this.$refs.myTable.clearSelected() but that did not seem to have any effect beyond setting my v-model to null.
Here is the table code:
<b-table
no-provider-filtering
ref="groupTable"
show-empty
stacked="md"
:items="ParamProvider"
:fields="fields"
striped
outlined
hover
class="bg-light"
:current-page="current_page"
:per-page="per_page"
:filter="filter"
:filter-included-fields="filterOn"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:sort-direction="sortDirection"
#filtered="onFiltered"
>
<template v-slot:cell(selected)="row">
<b-form-group>
<input type="checkbox" #click.stop="addToSelected(row.item, row.index)"/>
</b-form-group>
</template>
<template v-slot:cell(actions)="data">
<b-button size="sm" variant="danger" b-tooltip title="Delete"
#click.stop="removeItem(data.item, data.index)"><i
class="fa fa-trash"></i></b-button>
</template>
</b-table>

How to filter on a primeNG table with a dropdown and apply the filter only when pressing the apply button?

I am trying to filter a column in the primeNG table with a drop down menu, but I want to apply the filter only when I press the Apply button. Now filtering happens in the onChange event. If I remove the onChange event the filter does not work
This is the code without onChange event:
<p-table #dt1 [value]="customers">
<ng-template pTemplate="header">
<tr>
<th>
<div>
Status
<p-columnFilter field="status" matchMode="equals" display="menu" [showOperator]="false" [showMatchModes]="false">
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
<p-dropdown [ngModel]="value" [options]="statuses" placeholder="Any">
<ng-template let-option pTemplate="item">
{{option.label}}
</ng-template>
</p-dropdown>
</ng-template>
</p-columnFilter>
</div>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-customer>
<tr>
<td>
{{customer.status}}
</td>
</tr>
</ng-template>
</p-table>
When I press the Apply button the filter value is null
Here is a stackblitz: https://stackblitz.com/edit/primeng-tablefilter-demo-hbvzhe
I don't know if you still need the answer, but I'll post it anyway for other people to find it.
The documentation isn't really clear on the filterCallback element of the filter (feel free to tell me if i have missed something), but i managed to stop it from calling the lazy load with this code:
On the filter template itself:
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
<p-dropdown
[ngModel]="value"
(onChange)="customFilterCallback(filter, $event.value)"></p-dropdown>
</ng-template>
customFilterCallback(filter: (a) => void, value: any): void {
this.stopListening = true;
filter(value);
this.stopListening = false;
}
On the method listening to the onLazyLoad event of the table:
(onLazyLoad)="lazy_load($event)"
lazy_load(event: LazyLoadEvent): void {
if (this.stopListening) {
return;
}
...loading stuff
}
Using this solution you can stop the loading every time you change the custom filter.
Of course, the data displayed isn't going to match the filter until the "Apply" button is pressed (or until the lazy loading is triggered any other way).
It really would be better if the library provided a way to stop the onLazyLoad event when the filter is changed.
EDIT:
This of course only works for custom filters, when you add a new constraint to the default filter, it's going to trigger the lazy loading.
I have found another way by overriding the Apply and Clear buttons. My example relates to the selection of calendar dates, but the point is the same.
The filter template looks as follows:
<p-columnFilter field="createdDate" matchMode="between" [display]="'menu'" [showAddButton]="false"
[showMatchModes]="false" [showOperator]="false" [showClearButton]="false" [showApplyButton]="false">
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
<p-calendar #createdCalendar [inline]="true" [readonlyInput]="true" [selectionMode]="'range'"></p-calendar>
<div class="p-d-flex p-jc-between p-ai-center p-mt-3">
<p-button label="Clear" styleClass="p-button-outlined" (onClick)="filter(undefined)"></p-button>
<p-button label="Apply" (onClick)="filter(createdCalendar.value)"></p-button>
</div>
</ng-template>
</p-columnFilter>

Add multiple dialogs into a single page

I'm working into an Angular app that displays some data into a dataGrid as follows.
<p-dataGrid [value]="docs" [paginator]="true" [rows]="8">
<ng-template let-doc pTemplate="item">
<div class="ui-g-12 ui-md-3">
<span>{{doc.title}}</span>
</div>
</ng-template>
</p-dataGrid>
I'm trying to add a button, that when clicked, displays some info regarding the selected doc. I did it as follows:
<p-dataGrid [value]="docs" [paginator]="true" [rows]="8">
<ng-template let-doc pTemplate="item">
<div class="ui-g-12 ui-md-3">
<span>{{doc.title}}</span>
<button (click)="showDialog(doc.id)" pButton type="button" icon="fas fa-info-circle" iconPos="left" label="Details"></button>
<p-dialog id="{{doc.id}}" #{{doc.id}} [(visible)]="display" modal="modal" width="300" [responsive]="true">
<p>{{doc.title}}</p>
</p-dialog>
</div>
</ng-template>
</p-dataGrid>
Into my component, I added a function:
display: boolean = false;
showDialog(id: string) {
alert(id);
this.display = true;
}
The problem is since I'm using the same variable ("display") to control the visibility of all dialogs, browser gets lost about which dialog it should show/hide. In general, it uses the last one.
Since the quantity of elements into the screen is variable, I cannot create display1, display2, displayN variables. So my doubt is, how do I dynamically control the visibility of an element?
I tried something like with no luck:
showDialog(id: string) {
var e = document.getElementById(id);
e.attributes['ng-reflect-visible'].value = true;
}
There's no need to create as many p-dialog elements as docs. Only once should be enough. So if you extract yours p-dialog outside of your p-datagrid, HTML code becomes something like that :
<p-dataGrid [value]="docs" [paginator]="true" [rows]="8">
<ng-template let-doc pTemplate="item">
<div class="ui-g-12 ui-md-3">
<span>{{doc.title}}</span>
<button (click)="showDialog(doc.id)" pButton type="button" icon="fas fa-info-circle" iconPos="left" label="Details"></button>
</div>
</ng-template>
</p-dataGrid>
<p-dialog id="dialog" [(visible)]="display" modal="modal" width="300" [responsive]="true">
<h1>{{selectedDoc.title}}</h1>
Details : {{selectedDoc.details}}
</p-dialog>
where selectedDoc is assigned when you click on a button :
showDialog(id: string) {
this.selectedDoc = this.docs[id-1];
this.display = true;
}
Here is a working Plunker

Primeng autocomplete component with different colors for each item - normally they appear in the same color

Currently I want to use the primeng autocomplete multi select component: https://www.primefaces.org/primeng/#/autocomplete
What I need additionally is that every item which I want to select from as an autosuggestion should be colored differently.
E.g. If I have the options Paris (red), Munich (blue) the background should be shown in a different color.
Once you have assigned a colour for each of your countries, just use templating to apply it :
<p-autoComplete [(ngModel)]="country" [suggestions]="filteredCountriesSingle" (completeMethod)="filterCountrySingle($event)"
field="name" [size]="30" placeholder="Countries" [minLength]="1">
<ng-template let-country pTemplate="item">
<div class="ui-helper-clearfix" [ngStyle]="{'background-color':country.backgroundColor}">
{{country.name}}
</div>
</ng-template>
</p-autoComplete>
Check my Plunker where I defined a random colour for each country :
this.listOfCountries.forEach(function (item) {
item.backgroundColor = "#"+((1<<24)*Math.random()|0).toString(16);
});

How to perform row double click event in kendo ui grid angular 2?

How to display orginal cell value in cell template <span> tag in angular 2 kendo ui grid.
Code
<ng-container ngFor="let col of grid.ColModel">
<kendo-grid-column [title]="col.Label" [field]="col.Name" [locked]="col.Locked" width="250px" *ngIf="hiddenColumns.indexOf(col.Name) === -1" >
<template kendoCellTemplate let-dataItem let-rowIndex="rowIndex" >
<span (dblclick)="open(rowIndex)">**{{dataItem}}** </span>
</template>
</kendo-grid-column>
</ng-container>
The example provided by Melanie might have worked in the past, but will not work with the Angular 2/4 Grid (if you click on the plunker, it won't load).
I have to do lots of debugging as I ran into the same issue.
The solution in a simple grid was as follows:
<kendo-grid #myGrid [selectable]="true" (dblclick)="dblClickEvent(myGrid, $event)">
<kendo-grid-column field="User" title="User" width="100">
</kendo-grid-column>
</kendo-grid>
in your .ts file, implement the event as follows:
dblClickEvent(grid, event) {
// debugger;
console.log('the selected row Index is '+ event.path[1].rowIndex);
//use the following line if you want to get the clicked cell content:
console.log('clicked cell content'+ event.path[0].textContent);
}
This would give your the selected row index, from which you can
Hope this helps.
The first argument in your double-click handler needs to be the double-click event (which you can access as $event in your template). You should pass that first and rowIndex second.
In addition, you're probably missing a lot of click events since you're using a span and your content is inside of a padded cell. I'd recommend that you make your entire cell a click target, for example by changing it to a div and getting rid of the padding on the containing td.
So your cell template might look like:
<kendo-grid-column field="MyField">
<template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex">
<div class="innerCell" (dblclick)="onRowDoubleClick($event, rowIndex)">
{{dataItem.MyField}}
</div>
</template>
</kendo-grid-column>
And your function:
onRowDoubleClick(evt, rowIndex) {
alert('You clicked row ' + rowIndex + '!');
}
And your styling:
td { padding: 0 !important; }
td > .innerCell { padding: 7px; cursor: pointer; }
Example: Plunker
Update:
If you have a sortable grid, you need to implement cellClick and dblClick like here:
https://stackblitz.com/edit/angular-ac3jzd?file=app/app.component.ts
This works for both: sorted and non sorted kendo grids
Orginal answer:
We like to define the dblclick on the grid and not on each column, So the answer from Adam works for us perfectly in chrome, but not in firefox.
Problem is that the path property is non-standard on the mouseevent and not provided in firefox (probably not in safari too)
Based on Adam's solution, we have solved it with:
<kendo-grid [selectable]="true" (dblclick)="dblClickEvent($event)">
<kendo-grid-column field="User" title="User" width="100"></kendo-grid-column>
</kendo-grid>
and:
dblClickEvent(event) {
let rowIndex;
if (event.path) { // works on chrome and all browsers supporting path property in mouseevent
rowIndex = event.path[1].rowIndex;
} else { // should work on all browsers
rowIndex = event.target.parentElement.rowIndex;
}
if (typeof rowIndex === 'number' && rowIndex < this.data.length) {
// do something
}
}
(this aussumes that the user has clicked inside a td-element)
Note: this does not work if the grid was sorted

Resources