How to show heading based on value in angular? - javascript

I am trying to change the title based on item._id .i stored item in component.
this is my html
<h1 mat-dialog-title>{{item._id ? "Update" : "Add"}} animal</h1>
below is my dialog-overview-example.ts
import {Component, Inject} from '#angular/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '#angular/material';
/**
* #title Dialog Overview
*/
#Component({
selector: 'dialog-overview-example',
templateUrl: 'dialog-overview-example.html',
styleUrls: ['dialog-overview-example.css'],
})
export class DialogOverviewExample {
animal: string;
name: string;
item:string;
constructor(public dialog: MatDialog) {}
openDialog(): void {
item =[{"_id": "2","animal":"lion","weiht":"100"}];
let dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
width: '250px',
data: { name: this.name, animal: this.animal,item: this.item }
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
this.animal = result;
});
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
#Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
}
Demo
if _id is there in item heading should show update animal otherwise it should show Add animal in our case id already there in item so it should show update animal ..help me out

I could see that you have defined the item inside the component as an array. So you have to use the following code in HTML
<h1 mat-dialog-title>{{item[0]._id ? "Update" : "Add"}} animal</h1>

Related

Angular does not rerender on Input() change

Whatever i do angular does not detect change on talks array. I have a handleSubmit function to send the toolbar. Toolbar use it to send the changes to parent from input field.
My app.component.ts file
import { Component, Type, OnChanges, SimpleChanges } from '#angular/core';
import { getResponse } from '../api/API';
declare module '../api/API' {
export interface NlpAPI {
getResponse(data: any): Promise<any>;
}
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnChanges {
talks: string[];
title: string;
ngOnChanges(changes: SimpleChanges): void {
console.log(changes);
}
constructor() {
this.talks = [];
this.title = 'Talks';
}
ngOnInit() {
this.talks.push('Welcome to ProjectX! How can I help you?');
this.talks.push('I am a chatbot. I can help you with your queries.');
}
handleSubmit(data: any): void {
this.talks.push(data.talk);
}
messageResponse() {
// #ts-ignore: Object is possibly 'null'.
const x = document.getElementById('txt').value;
// #ts-ignore: Object is possibly 'null'.
document.getElementById('output').innerHTML =
'Your message is ' + '"' + x + '"';
}
}
My app.component.html
<!-- Toolbar -->
<app-custom-toolbar [handleSubmit]="handleSubmit"></app-custom-toolbar>
<!-- Highlight Card -->
<app-text-area [talksFromUser]="talks" [title]="title"></app-text-area>
<!-- Bottombar -->
<router-outlet></router-outlet>
My text-area.component.ts file
import { Component, Input, OnChanges, SimpleChanges } from '#angular/core';
#Component({
selector: 'app-text-area',
templateUrl: './text-area.component.html',
styleUrls: ['./text-area.component.css'],
})
export class TextAreaComponent implements OnChanges {
#Input() talksFromUser: string[] = [];
#Input() title: string = '';
constructor() {}
ngOnChanges(changes: SimpleChanges): void {
console.log(changes);
}
}
My text-area.component.html
<div class="main-text-area">
<div *ngFor="let item of talksFromUser">{{ item }}</div>
</div>
custom-toolbar.component.ts file
import { Component, Input, OnInit } from '#angular/core';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-custom-toolbar',
templateUrl: './custom-toolbar.component.html',
styleUrls: ['./custom-toolbar.component.css'],
})
export class CustomToolbarComponent implements OnInit {
talks: string[] = [];
#Input() handleSubmit!: (args: any) => void;
constructor() {}
ngOnInit(): void {}
onSubmit(f: NgForm) {
this.handleSubmit(f.value);
f.resetForm();
}
}
I tried also
this.talks = [...this.talks, data.talk]
Thank you all.
There are two issues in your code:
First one, you are calling handleSubmit("string") (so data is a string), but you are pushing data.talk, which is undefined (so talks will be [undefined, undefined, ...]). To fix it, use data:
handleSubmit(data: any): void {
this.talks.push(data); // use "data" instead of "data.talk"
}
Second one, you are using a AppComponent method into CustomToolbarComponent class. You need to keep the this scope of AppComponent. Also, you should use arrow functions:
handleSubmit = (data: any): void => {
this.talks.push(data);
}

Unable to calculate Total in my shopping-cart

I Have created a shopping cart with 2 components(Productlist and cart list). when I click on the 'add to cart' button in the product list it is successfully moving into the service file and from the service file to 'cart list' but Total was showing undefined. Please help me to solve this cart Total issue.
Product-list.ts file
import { Component, OnInit } from '#angular/core';
import { ProductService } from '../../../service/product.service';
import { CartService } from '../../../service/cart.service';
#Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
Productlist = [];
constructor(private productservice: ProductService,
private cartservice: CartService) {
this.Productlist = this.productservice.send()
}
ngOnInit(): void {
}
saveproduct(item) {
this.cartservice.get(item)
}
}
cart service file
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class CartService {
cartproducts = [{Name: 'Mobile', Price: 13000, Qty: 1}]
constructor() { }
send() {
return this.cartproducts
}
get(items) {
this.cartproducts.push(items)
console.log(this.cartproducts)
}
}
cart list file
import { Component, OnInit, ɵConsole, ɵɵNgOnChangesFeature } from '#angular/core';
import { CartService } from '../../../service/cart.service';
#Component({
selector: 'app-cart',
templateUrl: './cart.component.html',
styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit {
cartlist = [];
Total: number;
constructor( private cartservice: CartService) {
this.cartlist = this.cartservice.send()
console.log(this.cartlist);
console.log(this.Total);
}
ngOnInit() {
this.cartlist.forEach((_e: any) => {
this.Total += (_e.qty * _e.price);
});
}
}
When the Total property has been created, it is undefined by default until you assign it a value. You do assign a value to it in the ngOnInit but you calculate on an undefined value, so it returns undefined as well. Give Total a default value like so:
...
Total: number = 0;
...
Also the code you put in ngOnInit to calculate the Total, would be better placed in a get property. This way, Total will always be calculated when it's requested instead of pre-rendered and only calculated once. In that case your code would look like:
get Total(): number {
let value = 0;
this.cartlist?.forEach((_e: any) => {
value += (_e.qty * _e.price);
});
return value;
}

Display hierarchy selections in a list view in the order of selection

I am trying to implement a functionality which will display a list of nodes selected from the TreeNode structure, on the right.
Something similar to this plunkr I found : http://next.plnkr.co/edit/1Fr83XHkY0bWd9IzOwuT?p=preview&utm_source=legacy&utm_medium=worker&utm_campaign=next&preview
In my current method, I am getting the right-side list to be in the same hierarchy order as that on the left.
For eg : Even if I select node "B" before node "A", in the list, it still shows first A and then B (because A is above B in the displayed hierarchy).
Rightside.component.html :
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<ul class="selection-list">
<li *ngFor="let item of getSelections()">
<button class="btn" (click)="deselect(item)" *ngIf="item.selected">
<i class="fa fa-close"> {{ item.displayName }} </i>
</button>
</li>
</ul>
rightside.component.ts:
import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '#angular/core';
import { DataService } from '../../shared/service/data.service';
import { TreeNode } from '../../shared/dto/TreeNode';
import html from './rightside.component.html';
import css from './rightside.component.css';
#Component({
selector: 'rightside-component',
template: html,
providers: [DataService],
styles: [css],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class RightSideComponent implements OnInit {
selections: string[];
#Input() treeNode: TreeNode<string>[];
constructor(private cd: ChangeDetectorRef) {}
ngOnInit() {
}
getSelections() : TreeNode<string>[] {
if (typeof(this.treeNode) == "undefined" || (this.treeNode) === null) {
return [];
}
return this.treeNode;
}
deselect(item: TreeNode<string>): void {
if((item.children) !== null) {
item.children.forEach(element => {
this.deselect(element);
});
}
item.selected = false;
}
}
productline.component.html:
<p>Productlines</p>
<mat-input-container>
<input #searchInput matInput placeholder="Search for Product Line">
</mat-input-container>
<div class="flex-container">
<div class="PLCheck" *ngIf="isDataLoaded">
<fortune-select
(dataChanged)="onDataChange($event)"
[searchTerm]="searchInput.value"
[currentNode]="tree"
[singleSelect]="singleSelect"
[collapsed]="true"></fortune-select>
</div>
<div class="sendToRight">
<rightside-component
[treeNode]="selectedProductLine">
</rightside-component>
</div>
</div>
Productline.component.ts:
import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '#angular/core';
import * as API from '../../shared/api-routes';
import { DataService } from '../../shared/service/data.service';
import { ValidationService } from '../../shared/service/validation.service';
import { Subject } from 'rxjs/Subject';
import { BasestepComponent } from '../basestep-component/basestep.component';
import { TreeNode } from '../../shared/dto/TreeNode';
import html from './productline.component.html';
import css from './productline.component.css';
#Component({
selector: 'productline-component',
template: html,
providers: [DataService],
styles: [css],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProductlineComponent extends BasestepComponent<string> implements OnInit {
selectedProductLine: TreeNode<string>[];
constructor(dataService:DataService, cd:ChangeDetectorRef) {
super(dataService, cd);
}
ngOnInit() {
this.subject.subscribe((productline) => this.productLineChange(productline));
}
public productLineChange(productLine: TreeNode<string>[]):void {
this.selectedProductLine = productLine;
}
}
Basestep.component.ts:
import { Input, ChangeDetectorRef } from '#angular/core';
import { castTree, ReportTemplate } from '../report-common';
import { DataService } from '../../shared/service/data.service';
import { Subject } from 'rxjs/Subject';
import { ValidationService } from '../../shared/service/validation.service';
import { TreeNode } from '../../shared/dto/TreeNode';
export class BasestepComponent<T> {
public tree: TreeNode<T>;
public singleSelect: boolean = false;
public isDataLoaded: boolean;
public template: ReportTemplate;
#Input() templateSubject: Subject<ReportTemplate>;
#Input() subject: Subject<TreeNode<T>[]>;
constructor(private dataService:DataService, private cd: ChangeDetectorRef) {}
public onDataChange(event:TreeNode<T>[]):void {
if (!ValidationService.isNullOrUndefined(this.subject)) {
this.subject.next(event);
}
}
public markForCheck() {
this.cd.markForCheck();
}
public reset() {
this.tree = null;
this.isDataLoaded = false;
this.markForCheck();
}
}
I want the order on the right to be in the order in which the items are selected and not based on the hierarchy. Hence, even if A is above B in the hierarchy, I would want B to be shown and then A based on the selections.
Basically, I would like the selections to be displayed dynamically in the order that they are chosen.
EDIT 1:
Adding code for fortune-select.component.ts:
import { Component, Input, Output, EventEmitter } from '#angular/core';
import { TreeNode } from './../dto/TreeNode';
import html from './fortune-select.component.html';
import css from './fortune-select.component.css';
#Component({
selector: 'fortune-select',
template: html,
styles: [css],
})
export class FortuneSelectComponent<T> {
#Input() currentNode: TreeNode<T>;
#Input() collapsed: boolean = false;
#Input() linked: boolean = true;
#Input() searchTerm: string = '';
#Input() singleSelect: boolean = false;
#Output() dataChanged = new EventEmitter<TreeNode<T>[]>();
selectedRadioValue:T;
public checkboxChangedEvent():void {
let list:TreeNode<T>[];
this.currentNode.indeterminate = true;
if (this.linked) {
list = TreeNode.getTopLevelCheckedNodes(this.currentNode);
} else {
list = TreeNode.getAllCheckedNodes(this.currentNode);
}
this.dataChanged.emit(list);
}
public radioChangedEvent(event:TreeNode<T>):void {
this.dataChanged.emit([event]);
}
}
Is there a way I could maybe store every selection in a list and then display the list? That way, it will show the selections in order. Right now, the entire structure is getting traversed, hence it displays in the tree's order.
Is there a way to do this?

Closing angular material dialog box

Learning angular2 material. I have the modal finally opening. But issue is when I click out side of modal it closes (not desired result right now) but thats not the current issue. When I click cancel the modal is not closing and throwing error. If I keep the this.dialogRef.close() commented out the app builds but when clicking the close button the modal does not close. If i uncomment that line the application does not build.
Any suggetions or what am I missing for this to work properly?
Thanks
Troy
Here is my componet(s) code:
import { Component, OnInit, Inject } from '#angular/core';
import { IGame } from './game/game';
import { Game } from './models/game.model';
import { GameService } from './services/game-service';
import { FormControl } from '#angular/forms';
import { Observable } from 'rxjs/Observable';
import { MdSnackBar } from '#angular/material';
import { MdDialog, MdDialogRef, MD_DIALOG_DATA} from '#angular/material';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
games: any[] = [ ];
selectedRow: Object;
setClickedRow: Function;
myControl: FormControl = new FormControl();
animal: string;
name: string;
girl: string;
options = [
'Football',
'Basketball',
'Baseball',
'Lacrosse',
'Volleyball'
];
filteredOptions: Observable<string[]>;
constructor(private _gameService: GameService,public snackBar: MdSnackBar,
public dialog: MdDialog) {
this.filteredOptions = this.myControl.valueChanges
.startWith(null)
.map(val => val ? this.filter(val) : this.options.slice());
}
filter(val: string): string[] {
return this.options.filter(option =>
option.toLowerCase().indexOf(val.toLowerCase()) === 0);
}
onSelect(game: Game): void {
this.selectedGame = game;
}
openSnackBar(message) {
this.snackBar.open(message,null, {
duration: 2000,
});
}
openDialog(): void {
let dialogRef = this.dialog.open(DialogDataExampleDialog, {
width: '250px',
data: {
animal: this.animal,
girl:this.girl
}
});
dialogRef.afterClosed().subscribe(result => {
this.animal = result;
this.girl = result;
console.log('The dialog was closed: ' + result.animal + ' ' +
result.girl);
});
}
ngOnInit() {
return this._gameService.getGames()
.subscribe(
(gameData) => this.games = gameData,
(error) => this.openSnackBar("Something broke!"),
()=> this.openSnackBar("Data loaded successfully")
);
}
}
#Component({
selector: 'dialog-data-example-dialog',
template: `
<div md-dialog-content>
<p>What's your favorite animal?</p>
<md-form-field>
<input mdInput tabindex="1" [(ngModel)]="data.animal">
</md-form-field>
<p>Whos's your favorite white girl</p>
<md-form-field>
<input mdInput tabindex="2" [(ngModel)]="data.girl">
</md-form-field>
</div>
<div md-dialog-actions>
<button md-button [md-dialog-close]="data" tabindex="2">Ok</button>
<button md-button (click)="onNoClick()" tabindex="-1">No Thanks</button>
</div>
`,
})
export class DialogDataExampleDialog {
constructor(dialogRef: MdDialogRef<DialogDataExampleDialog>,
#Inject(MD_DIALOG_DATA) public data: any) {}
onNoClick(): void {
/*this.dialogRef.close();*/
}
}

Angular2 call function from another component

I have two components: NgbdAlertCloseable and AlertCtrl. Also I have AppComponent as parent component. What I want is to click a button in AlertCtrl component and create the alert on NgdbAlertCloseable component.
addSuccess() function adds an alert to the view and it worked well while I call it inside of its component. However, I tried to use an EventEmitter to call this function from another component (as suggested here: https://stackoverflow.com/a/37587862/5291422) but it gives this error:
ORIGINAL EXCEPTION: TypeError: self._NgbdAlertCloseable_2_4.addSuccess is not a function
Here are my files:
ngbd-alert-closeable.component.ts
import { Input, Component } from '#angular/core';
#Component({
selector: 'ngbd-alert-closeable',
templateUrl: './app/alert-closeable.html'
})
export class NgbdAlertCloseable {
#Input()
public alerts: Array<IAlert> = [];
private backup: Array<IAlert>;
private index: number;
constructor() {
this.index = 1;
}
public closeAlert(alert: IAlert) {
const index: number = this.alerts.indexOf(alert);
this.alerts.splice(index, 1);
}
public static addSuccess(alert: IAlert) {
this.alerts.push({
id: this.index,
type: 'success',
message: 'This is an success alert',
});
this.index += 1;
}
public addInfo(alert: IAlert) {
this.alerts.push({
id: this.index,
type: 'info',
message: 'This is an info alert',
});
this.index += 1;
}
}
interface IAlert {
id: number;
type: string;
message: string;
}
alert-ctrl.component.ts
import { EventEmitter, Output, Component } from '#angular/core';
import { NgbdAlertCloseable } from './ngbd-alert-closeable.component';
#Component({
selector: 'alert-ctrl',
template: '<button class="btn btn-success" (click)="addSuccessMsg()">Add</button>'
})
export class AlertCtrl {
#Output() msgEvent = new EventEmitter();
public addSuccessMsg(){
this.msgEvent.emit(null);
}
}
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: '<div class="col-sm-4"><alert-ctrl (msgEvent)="ngbdalertcloseable.addSuccess()"></alert-ctrl><ngbd-alert-closeable #ngbdalertcloseable></ngbd-alert-closeable>'
})
export class AppComponent { }
Am I using it wrong? How can I fix that?
Check that the addSuccess function is static and is using non static properties.
Should be:
public addSuccess(alert: IAlert) {
this.alerts.push({
id: this.index,
type: 'success',
message: 'This is an success alert',
});
this.index += 1;
}
And in your view you must pass the IAlert value in this example we'll send that value when we call msgEvent.emit(IAlert).
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: '<div class="col-sm-4"><alert-ctrl (msgEvent)="ngbdalertcloseable.addSuccess($event)"></alert-ctrl><ngbd-alert-closeable #ngbdalertcloseable></ngbd-alert-closeable>'
})
export class AppComponent { }
Then you must send that IAlert, I'll change your AlertCtrl just for demo purpose.
import { EventEmitter, Output, Component } from '#angular/core';
import { NgbdAlertCloseable } from './ngbd-alert-closeable.component';
#Component({
selector: 'alert-ctrl',
template: '<button class="btn btn-success" (click)="addSuccessMsg()">Add</button>'
})
export class AlertCtrl {
currentAlert:IAlert = {id: 0, type: 'success', message: 'This is an success alert'};
#Output() msgEvent = new EventEmitter<IAlert>();
public addSuccessMsg(){
this.msgEvent.emit(this.currentAlert);
}
}
Good luck and happy coding!

Categories

Resources