rowStyleClass function seems no to be called on datatable - primeng

I'm using angular 2.4.1 with primeng 1.1.4 but I tried with 1.1.3 and 2.0.1 with no luck.
I'd like to conditionaly change style of rows according to their content with rowStyleClass but it seems that the referenced function customRowClass is never called.
Here is the html code :
<p-dataTable [value]="products" [rowStyleClass]="customRowClass">
<p-column field="name" header="Name"></p-column>
</p-dataTable>
and the summary of the component :
#Component({
selector: 'products',
templateUrl: './products.component.html',
providers: [DataTableModule, SharedModule]
})
export class ProductsComponent implements OnInit, OnDestroy {
products: Product[] = [];
constructor(
private productsService: ProductsService
) { }
public customRowClass(rowData, rowIndex): string {
console.log('styling')
return "text-gray"
}
…
}
There is no log inside the console, the row text and its html remains unchanged.
Any idea on what I did wrong ?

Related

Implementing ng2-completer

I am currently using ng2-completer (https://github.com/oferh/ng2-completer) for angular 2 and struggling to add in the suggestions to have the full response instead of just having one value.
Also, when the suggestion is selected, how is the method assigned to handle this?
The code I've got so far is:
import { Component } from '#angular/core';
import { AutoComplete } from './autocomplete';
import { CompleterService, CompleterData, RemoteData } from 'ng2-completer';
import { SearchComponent } from './search.component';
import { QueryService } from './query.service';
#Component({
selector: 'app-home',
template: `<ng2-completer [(ngModel)]="searchStr" [dataService]="dataService" [minSearchLength]="0" [inputClass]="['form-control input-list']" [autofocus]="['true']" [selected]="selected()"></ng2-completer>`,
//directives: [ AutoComplete ]
})
export class HomeComponent {
public searchStr: string;
private dataService: CompleterData;
constructor(private completerService: CompleterService, private queryService: QueryService) {
//this.dataService = completerService.local(this.searchData, 'color', 'color');
this.dataService = completerService.remote('http://localhost:61227/machine/?query=','ComputerHostname, AssetID', 'ComputerHostname').descriptionField('ComputerType');
//this.dataService = this.queryService.search(searchStr).then(items => this.items = items);
}
selected () {
console.log("test");
}
}
However it shows the following error:
Can't bind to 'selected' since it isn't a known property of 'ng2-completer'.
selected is an event and not a property and therefor the syntax for it (as described in Angular template syntax) should be (selected)="selected($event)"
autofocus expects a boolean value (see in ng2-completer doc) not an array so you should use [autofocus]="true"

Add Property to my NPM Module

This might be answered, but damn if I can find it . I am creating a module, and its working, the issue is I want to assign a property to another property on my module.
so in angular 2 (with ng-module) I have created a simple panel
<simple-panel name="MyPanel"></simple-panel>
I have it working great, the issue is I want to assign a property to the name Property now and I have no idea what is the best way to do this.
so I would like to return {{MyPanel.thisProperty}} for use on the page where I am calling the tag.
here is a sample of what I am doing, stripped down for this question
here is my simple-panel.ts
import {Component,NgModule,ModuleWithProviders, Directive, Input} from '#angular/core';
/**
* Content of the edit panel.
*/
#Directive({
selector: 'simple-panel-edit-panel-content'
})
export class SimplePanelEditPanelContent {}
#Component({
selector: 'simple-panel',
templateUrl: 'simple-panel.html',
styleUrls: ['simple-panel.css'],
encapsulation: ViewEncapsulation.None
})
export class SimplePanel{
private _name: string;
private _announceedit: boolean = false;
private _buttonname: string = 'edit';
/** This sets the Name as a variable that can be used. */
#Input()
get name(): string { return this._name; }
set name(value) { this._name = value; }
/**Sets the Edit Announcement */
#Input()
get editannounce(): boolean { return this._announceedit; }
set editannounce(value: boolean) {
if (!value) {
this._announceedit = true;
this._buttonname = 'search';
}else{
this._announceedit = false;
this._buttonname = 'edit';
}
}
}
#NgModule({
exports: [SimplePanel,SimplePanelEditPanelContent],
declarations: [SimplePanel,SimplePanelEditPanelContent],
})
export class SimplePanelComponent {
static forRoot(): ModuleWithProviders {
return {
ngModule: SimplePanelComponent,
providers: []
};
}
}
here is the simple-panel.html
<md-card>
<md-card-title-group>
<button md-raised-button (click)="editannounce=editannounce;"><md-icon>{{ _buttonname }}</md-icon></button>
</md-card-title-group>
<md-card-content>
<ng-content select="simple-panel-edit-panel-content"></ng-content>
</md-card-content>
<md-card-actions>
<button md-raised-button (click)="editannounce = editannounce"><md-icon>save</md-icon> SAVE</button>
</md-card-actions>
</md-card>
when someone uses the module, a panel is created with a button
when someone clicks the button I can access the variable within the template above, but what I want to do is actually access a variable that is used on the page itself where they call the module to use. it would be nice to have it named MyPanel.announceedit or MyPanel.editable as an example, but the main thing is that a variable is created, and watched, when it changes it passes it back up to where the module is bieng used and allows user the ability to access it within the content area, so if they added an input and wanted to see if the button was clicked to set the readOnly attribute they could. Hopefully this makes more sense.
If you write it like
<simple-panel [name]="MyPanel"></simple-panel>
in the component that includes this html, you can access/set MyPanel with a simple this.MyPanel.
And in your SimplePanel component
#Input() name;
...
this.name = "something";
is again all you need to set and get that field.

Select the text inside an input using Typescript in Angular 2

I'm trying to do exactly what is described in this post, but in Angular2.
Basically use the javascript function .setSelectionRange(start, end); in an input after a user clicks on a trigger. I can't find any way to replicate this behaviour using Typescript.
Thanks in advance.
I can't find any way to replicate this behaviour using Typescript.
TypeScript is just JavaScript. I suspect you mean to say Angular2 (that post is Angular1).
Angular2
You need to get a hold of the dom element (which is what you seem to be struggling with). In your controller you need to inject ElementRef. E.g. #Inject(ElementRef) elementRef: ElementRef,
Once you have the element you can traverse it and do whatever dom access / manual manipulation you need to do.
More
Docs : https://angular.io/docs/js/latest/api/core/ElementRef-class.html
Example
Sample : https://stackoverflow.com/a/32709672/390330
import {Component, ElementRef} from 'angular2/core';
#Component({
selector:'display',
template:`
<input #myname (input) = "updateName(myname.value)"/>
<p> My name : {{myName}}</p>
`
})
class DisplayComponent implements OnInit {
constructor(public element: ElementRef) {
this.element.nativeElement // <- your direct element reference
}
ngOnInit() {
}
}
This example line of code shows the essence of selecting the text (with .name being an ElementRef reference):
this.name.nativeElement.setSelectionRange(0, 999);
Here are all the necessary pieces put together (as well as putting focus on the input) for a "name" field:
View:
<input name="name" formControlName="name" type="text" [(ngModel)]="data.name">
Component:
export class MyComponent {
#ViewChild('name') name: ElementRef; // * see security comment below for ElementRef
#Input() data: {name: 'Foo Baz'};
myForm: FormGroup;
constructor() {
this.myForm = new FormGroup({
name: new FormControl()
});
}
// call this to give the field focus and select its text
focusAndSelectNameFieldText(){
if (!this.name) return;
this.name.nativeElement.focus();
setTimeout(() => {
this.name.nativeElement.setSelectionRange(0, 999);
});
}
}
*Please be sure your use of ElementRef does not pose a security risk:
https://stackoverflow.com/a/44509202/442665

How to pass function callback from one component to another component in ng-forward

I have created two components named as Alert ticker and dropdown.
These two are separate component.
So lets come to the point.
I am using this alert ticker in some other page named as Dashboard.
so I am passing the callback function from dashboard page to ticker component and ticker component pass this callback function to dropdown component.
Dashboard.html
<ticker [data]="data"
poll-time="10"
[filter-data]="filterData"
(on-polling)="onTickerPoll($event);"
(on-scroll)="onTickerScroll($event);"
(on-selection)="onTickerFilterChange($event);"></ticker>
Ticker.html
<dropdown [list]="ctrl.filterData" (on-selection)="ctrl.onSelection($event)" ddl-class="form-control"></dropdown>
Ticker.ts
#Component({
selector: 'od-ticker',
directives: [DropdownComponent],
templateUrl: '/app/components/ticker/ticker.html'
})
export class TickerComponent {
#Input() data;
#Output() onSelection: EventEmitter < string > = new EventEmitter();
}
But I am unable to do this .
Please advice.
There is a nice discussion on the Angular2 issue tracker about: "Why EventEmitter doesn't bubble up ?". This discussion is here.
So I think that you have to expose the event in the whole hierarchy of components...
I propose the following solution :
Dashboard.ts :
import {Component} from 'angular2/core';
import {MyTicker} from './my-ticker'
#Component({
selector: 'dashboard-app',
template: `<my-ticker [datas]="dashBoardDatas" (onSelection)="selectValueChanged($event)"></my-ticker>`,
directives: [MyTicker],
})
export class DashboardApp {
private dashBoardDatas: Array<string>;
constructor(){
this.dashBoardDatas = ["toto", "tata"];
}
selectValueChanged(value: string){
console.log('Selected value changed to :' + value);
}
}
And MyTicker.ts :
import {Component, Input, Output, EventEmitter, AfterViewInit} from 'angular2/core';
import {MySelect} from './my-select'
#Component({
selector: 'my-ticker',
template: `
<p>
<my-select [datas]="datas" (onSelection)="onSelection.emit($event)"></my-select>
</p>
`,
directives: [MySelect]
})
export class MyTicker {
#Input() datas: Array<string>;
#Output() onSelection: EventEmitter < string > = new EventEmitter();
constructor() {}
ngAfterViewInit(){
console.log("Datas in ticker : " + this.datas);
}
}
And MySelect.ts :
import {Component, Input, Output, EventEmitter} from 'angular2/core';
#Component({
selector: 'my-select',
template: `
<p>
<select name="filter" (change)="onSelection.emit($event.target.value)">
<option *ngFor="#item of datas" value="{{item}}">{{item}}</option>
</select>
</p>
`
})
export class MySelect {
#Input() datas: Array<string>;
#Output() onSelection: EventEmitter < string > = new EventEmitter();
constructor() {}
}
I did the following Plunkr to illustrate this.
As you can see, in the Dashboard, I have a method that I want to trigger when the content of the ticker's select change (selectValueChanged) (that is triggered when my-select selection change)... So we have to re-define the event emitter in "MyTicker".
The ticker and select contains the same members as in you question. An event emitter, and the filter's datas. When the select value change, I emit the event (thanks to (change)="onSelection.emit($event.target.value)" ).
This event is "catched" by the ticker and re-emited, and then catched by dashboard (thanks to "(onSelection)="selectValueChanged($event)". So the method "selectValueChanged" of Dashboard is called when the event "OnSelection" of MySelect is fired.
Thanks guys for your help.
I have got the way to accomplish this.
#Output() onScroll: EventEmitter<string> = new EventEmitter();
#Output() onSelection: EventEmitter<string> = new EventEmitter();
onFilterChange(data){
this.onSelection.next(data);
}
onScrollEnd(){
this.onScroll.next({});
}
Ticker.html
<dropdown [list]="ctrl.filterData" (on-selection)="ctrl.onFilterChange($event)" ddl-class="form-control"></dropdown>

Angular2 component view updated continuously

I have an Angular 2 component that displays a list of Items, and that registers to a service that publishes events. The problem is that even if I don't do anything when I receive an event, Angular updates the view (or at least do something when, I guess, it shouldn't).
Here is a plunker.
As you can see in the console, the "getTitle()" method of my items is called each time my service publishes a message.
Even if I don't register to my service and if my component doesn't implement the MyServiceListener interface, getTitle is called each time the service gets a message. If I don't give the service to my component in its constructor, everything is fine. So, something seems wrong with my dependency injection, but what?
Here is the relevant code of the plunker:
My service and its listeners interface:
export interface MyServiceListener {
onMessage(_message: any);
}
export class MyService {
private m_listener: MyServiceListener;
constructor() {
window.setInterval(() => {
if (this.m_listener !== undefined) {
this.m_listener.onMessage("Hi");
}
}, 500);
}
setListener(_listener: MyServiceListener) { this.m_listener = _listener; }
}
The Item class:
export class Item {
m_title: string;
constructor(_title: string) {
this.m_title = _title;
}
getTitle(): string { console.log("getTitle"); return this.m_title; }
}
My component:
#Component({
selector: 'my-app',
template : `
<div>
<ul>
<li *ng-for="#item of m_items">
{{item.getTitle()}}
</li>
</ul>
</div>
`
})
export class App implements TestBugAngularServiceListener {
private m_items: Array<Item> = new Array<Item>();
constructor(_communicationService: MyService) {
this.m_items.push(new Item("A"));
this.m_items.push(new Item("B"));
this.m_items.push(new Item("C"));
_communicationService.setListener(this);
}
onMessage(_message: any) {
}
}
bootstrap(App, [MyService]).catch(err => console.error(err));
Both articles : Change detection and Angular immutability explain a lot of thing about how Angular 2 detect changes of object, and how the tree of components in angular 2 is traversed to perform data binding...
In your sample, I think your component "my-app" can be considered to be "Immutable", so changing its "change detection strategy" to OnPush solve your problem.
You can write this :
#Component({
selector: 'my-app',
changeDetection: ChangeDetectionStrategy.OnPush,
template : `
<div>
<ul>
<li *ng-for="#item of m_items">
{{item.getTitle()}}
</li>
</ul>
</div>
`
})
And after adding the import to ChangeDetectionStrategy, databinding of "my-app" will not be computed after each browser event, but only when its input change, so never...

Resources