Is it possible to add a tooltip to column title in ng2-smart-table - ng2-smart-table

Is it possible to add a tooltip to a column title in a ng2-smart-table?
We are using "ng2-smart-table": "1.4.0", "#angular/core": "7.2.16"
We have a tooltipComponent, below, this works great on the cell, we want to have the tooltip display when the user hover's over the title of the column not on the cell. I've not had any luck finding an example.
import { Component, OnInit, Input, EventEmitter, Output, NgModule } from '#angular/core';
#Component({
selector: 'tooltip-view',
template: `
<button type="button" class="btn btn-outline-secondary" ngbPopover={{TooltipText}} triggers="mouseenter:mouseleave" popoverTitle={{TooltipTitle}}>
{{ value }}
</button>
`,
})
#NgModule()
export class TooltipComponent implements OnInit {
renderValue: string | number;
#Input() value: string | number;
#Input() rowData: any;
#Output() save: EventEmitter<any> = new EventEmitter();
ngOnInit() {
//this.renderValue = this.renderValue.toString().toUpperCase();
}
onClick() {
this.save.emit(this.rowData);
}
}
In the settings colums:
clin: {
title: 'CLIN',
type: 'custom',
filter: false,
renderComponent: TooltipComponent,
onComponentInitFunction(instance) { instance.TooltipText = 'This is the tooltip text for CLIN',
instance.TooltipTitle ='Help for CLIN'; }
},
Would like to move this functionality from a table cell to title, is this possible? Are there an examples of this?

Related

Angular textarea input not showing value/contents, despite showing up in html

I insert a textarea component into my template like so:
<div class="card-body" *ngIf="isEditing">
<app-text-area input-id="body" input-value="This is my default input value"></app-text-area>
</div>
The template of app-text-area is like so:
<textarea
placeholder="This is my placeholder"
[name]="inputID"
(input)="onInputChanged($event)"
ngModel>
{{ inputValue }}
</textarea>
The subsequent rendered HTML is like so:
<textarea _ngcontent-owj-c62="" placeholder="This is my placeholder" ngmodel="" ng-reflect-model="" ng-reflect-name="body" class="ng-pristine ng-valid ng-touched">
This is my default input value
</textarea>
However on the actual page, the inputValue text doesn't show up anywhere, the textarea acts as though it is empty, even showing the placeholder text. I can see the value in the html, though when I start typing in the box it replaces it as if it weren't there. The console shows no errors.
If I remove ngModel from the textarea, it fixes it
My app-text-area component ts is:
import { Component, EventEmitter, Input, OnInit, Output } from '#angular/core';
import { ControlContainer, NgForm } from '#angular/forms';
#Component({
selector: 'app-text-area',
templateUrl: './text-area.component.html',
viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ],
styleUrls: ['./text-area.component.scss']
})
export class TextAreaComponent implements OnInit {
#Input("input-id") public inputID: string = "text";
#Input("input-value") public inputValue: string;
constructor() { }
ngOnInit(): void {
}
public onInputChanged(event: Event):void {
let newValue = (event.target as HTMLTextAreaElement).value;
this.inputValue = newValue;
}
}
Hard to help without seeing the component.ts file
But a solution would be something in the lines of the following:
HTML template:
<textarea
[name]="inputID"
(input)="onInputChanged($event)"
[value]="inputValue">
</textarea>
<p>{{inputValue}}</p>
And the component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-text-area',
templateUrl: './text-area.component.html',
styleUrls: ['./text-area.component.css']
})
export class TextAreaComponent implements OnInit {
inputID:number=1;
inputValue:string="This is my placeholder";
constructor() { }
ngOnInit(): void {
}
onInputChanged(event:any){
this.inputValue=event.target.value;
}
}
This would set the initial value as "This is my placeholder" and would update the value on each change in the input displayed inside the p tag
I managed to fix this by setting [ngModel]="inputValue" instead of the defaultValue, value, or placing inputValue inside the textarea itself.

Angular innerHtml

I am relative new in Angular and I have the following question.
I have a component: my.component.html
<app-loading *ngIf="loading" message="Inhalt wird geladen..." delay="0"></app-loading>
<div [innerHtml]="content | safeHtml"></div>
And the following ts file: my.component.ts
export class MyComponent implements OnInit {
loading: boolean;
#Input() serviceUrl: string;
content: string;
constructor(public service: MyService) { }
ngOnInit() {
this.loading = true;
this.content = '';
this.service.getMyContent(this.serviceUrl).then(myContent => this.onMyContentRead(myContent));
}
onMyContentRead(dto: SimpleDto) {
this.loading = false;
this.content = dto.output;
}
}
It calls a REST service and gets the dto.output, which is a string contains the following html content from MyClassToShow.html
<li id="myBox_panels">
%s
<app-tooltip [myText]="test"></app-tooltip>
</li>
The tooltip components exists, and looks like this:
#Component({
selector: 'app-tooltip',
template: `
<a class="help" [pTooltip]="myText" [tooltipPosition]="tooltipPosition" </a>
})
export class TooltipComponent implements OnInit {
tooltipPosition: string;
#Input() myText;
constructor(private el: ElementRef) { }
ngOnInit() {
this.setTooltipPosition();
}
setTooltipPosition() {
....
}
It seems that the app-tooltip selector is not realized, because its template content is not displayed on the webpage, altough I can see the selector on the console log.
The innerHtml can only contain plain HTML code?
How can I get my app-tooltip template as well?
Thnak you a lot in advance!

Kind of recursive usage of an Component possible?

After searching for like two hours for a solution I decided to ask some pros suspecting the solution could be quite simple.
It is an Angular7 project.
I would like to have a "goal" in my goals component with a button "+". When you click that button I want to have annother goal being added to the page. So I want to click a button of the goal component to create a new goal, which is something like recursive to me.
goals.component.html:
<input type="text" value="Ich brauche einen Laptop für maximal 1000 Euro.">
<br/>
<br/>
<app-goal id="{{lastGivenId+1}}"></app-goal>
goals.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-goals',
templateUrl: './goals.component.html',
styleUrls: ['./goals.component.scss']
})
export class GoalsComponent implements OnInit {
lastGivenId: number = 0;
constructor() { }
ngOnInit() {
}
}
goal.component.ts and goal.component.html:
//Typescript code
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-goal',
templateUrl: './goal.component.html',
styleUrls: ['./goal.component.scss']
})
export class GoalComponent implements OnInit {
#Input() id : number;
constructor() { }
ngOnInit() {
}
onAddLowerGoal(currentGoalID:number){
// var goalElement = document.registerElement('app-goal');
// document.body.appendChild(new goalElement());
let newGoal = document.createElement("app-goal");
newGoal.setAttribute("id", "999");
let currentGoal = document.getElementById(currentGoalID.toString());
document.body.insertBefore(newGoal, currentGoal);
}
}
<html>
<div id="{{id}}" class="goal">goal{{id}}</div>
<button id="AddLowerGoal1" (click)="onAddLowerGoal(999)">+</button>
</html>
This way, it creates an app-goal element, but the div and button elements within the app-goal element is missing.
How can this problem be solved? Any help is welcome. Thanks in advance.
First glance: delete the html tags from your goal.component.html file.
Next: you can recursively add app-goal using angular. Inserting app-goal element the javascript way only adds the <app-goal></app-goal> object. It doesn't create an angular component. It doesn't bind your data.
Also if you're using Angular's #Input, you need to assign a component input with square braces. Do not use tags.
goals.component.html:
<input type="text" value="Ich brauche einen Laptop für maximal 1000 Euro.">
<br/>
<br/>
<app-goal [id]="lastGivenId+1"></app-goal>
goal.component.html:
<div id="{{id}}" class="goal">goal{{id}}</div>
<button id="AddLowerGoal1" (click)="onAddLowerGoal(999)">+</button>
<div *ngFor="let subGoal of subGoals">
<app-goal [id]="subGoal.id"></app-goal>
</div>
goal.component.ts:
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-goal',
templateUrl: './goal.component.html',
styleUrls: ['./goal.component.scss']
})
export class GoalComponent implements OnInit {
#Input() id : number;
subGoals: Array<any> = [];
constructor() { }
ngOnInit() { }
onAddLowerGoal(currentGoalID: number){
this.subGoals.push({id: currentGoalID});
}
}
You can also use a service to store your goals and subgoals to access them later.
I think what you're looking for is a Reactive Form with FormArray with dynamically added form controls.
Take a look at this for eg:
import { Component } from '#angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '#angular/forms';
#Component({...})
export class GoalsComponent {
goalsForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.goalsForm = this.fb.group({
goals: this.fb.array([])
});
}
onFormSubmit() {
console.log('Form Value: ', this.goalsForm.value);
}
get goals() {
return (<FormArray>this.goalsForm.get('goals')).controls;
}
addGoal() {
(<FormArray>this.goalsForm.get('goals')).push(this.fb.control(null));
}
}
And here's the template for this:
<h2>Goals:</h2>
<form [formGroup]="goalsForm" (submit)="onFormSubmit()">
<button type="button" (click)="addGoal()">Add Goal</button>
<hr>
<div *ngFor="let goal of goals; let i = index;" formArrayName="goals">
<div>
<label for="goal">Goal {{ i + 1 }}: </label>
<input type="text" id="goal" [formControlName]="i">
</div>
<br>
</div>
<hr>
<button>Submit Form</button>
</form>
Here's a Sample StackBlitz for your ref.

Angular 4 SideNav does not display

I am trying to insert a Material Sidenav into my component. For some reason, when I try to insert a basic sidenav it does not show anything -- main content, button to trigger sidenav, nor side content. I have imported both { MatSidenavModule } and { MatButtonModule} . However, if I comment out the mat-sidenav portion of the code, then the button will appear, so I think it may be an issue with the way I am setting up mat-sidenav.
Here is my HTML code:
<!--product.component.html-->
<h2>Store Inventory</h2>
<div class = "products">
Remaining: {{displayRemain}}
Requested: {{displayRequest}}
{{title}}
Total: {{cartTotal}}
</div>
<div>
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav class="example-sidenav">
Sidenav opened!
</mat-sidenav>
<div class="example-sidenav-content">
<button type="button" mat-button (click)="sidenav.open()">
Open sidenav
</button>
</div>
</mat-sidenav-container>
</div>
Here is the corresponding product.component.ts file: (I took out some functions which I commented out in the HTML)
import { Component, OnInit } from '#angular/core';
import { Product } from '../product';
import { ProductService } from '../product.service';
import {element} from 'protractor';
#Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css']
})
export class ProductsComponent implements OnInit {
products: Product[];
displayRemain: number;
displayRequest: number;
title: string;
prevRemain: number;
cartTotal: number;
constructor(private productService: ProductService) {
}
ngOnInit() {
this.title = 'Not Hello';
this.displayRemain = 0;
this.displayRequest = 0;
this.prevRemain = 10;
this.cartTotal = 0;
this.getProducts();
}
EDIT: got the answer, I didn't install the angular material animation library. Leaving this up in case others have the same problem.
Try to use sidenav.toggle() instead sidenav.open()
Regards

Angular 2 dialog popup with text field input

I have a simple popup that shows a message with OK button to release it, what I want is to add to this popup a text field that the user will need to type something in it and click OK to submit his answer.
currently it looks like this:
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<button md-button (click)="dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
constructor( public dialog: MdDialogRef<DialogComponent>) { }
}
and im using it like:
public showDialog(message: MessageBoxMessage) {
if (typeof message !== 'undefined') {
let dialogRef: MdDialogRef<DialogComponent> = this._dialog.open(DialogComponent);
dialogRef.componentInstance.title = message.title;
dialogRef.componentInstance.message = message.content;
}
}
how can I change it to have a popup with text-field and ok button tht pass me the value of the text-field?
You can create EventEmitter in your dialog:
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<mat-form-field class="example-full-width">
<input matInput placeholder="Favorite food" #input>
</mat-form-field>
<button mat-button (click)="onOk.emit(input.value); dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
onOk = new EventEmitter();
constructor( public dialog: MatDialogRef<ErrorDialogComponent>) { }
}
then subscribe to it in parent component
dialogRef.componentInstance.onOk.subscribe(result => {
this.resultFromDialog = result;
})
Plunker Example
Another way is passing value to MatDialog.close method
(click)="dialog.close(input.value)"
....
dialogRef.afterClosed().subscribe(result => {
this.resultFromDialog = result;
});
Plunker Example
You can bind the answer to a model like this :
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<input type="text" name="data" [(ngModel)]="data">
<button md-button (click)="dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
data: string;
constructor( public dialog: MdDialogRef<ErrorDialogComponent>) { }
}
And then bind the (click) to a function that sends your data.