I woudlike to send data selected from my another component (variable in file .ts)
.html :
<div class="liste">
<select class="form-control" name="Container" (change)="selectChangeHandler($event)">
<option disabled selected value> -- select an Container -- </option>
<option *ngFor="let v of values;let i = index" [value]="i">
{{v.Name}}
</option>
</select>
</div>
<div class="tableau" *ngIf="show" >
<table align="center">
<tr align="center"><b>{{selectedValue.Name}}</b></tr>
<tr align="center"><td>Matricule: {{selectedValue.Matricule}}</td></tr>
<tr align="center"><td>Material: {{selectedValue.Material}}</td></tr>
<div class="modal-body">
<app-heat-local> </app-heat-local>
</div>
How can I get value for this component with using to send my data in this component ?
another component .html (heat-local):
<h6 class="container-name">{{selectedValue.Name}}</h6>
my file .ts :
import {Component, OnDestroy, OnInit} from '#angular/core';
import {Cell} from 'app/data/cell';
#Component({
selector: 'app-heat-global',
templateUrl: './heat-global.component.html',
styleUrls: ['./heat-global.component.css'],
providers: [HeatService]
})
export class HeatGlobalComponent implements OnInit{
selectedValue = {
Name: '',
Matricule: '',
Material:'',
Quantity:'',
Coordonates:'',
}
values = [{
Name: "Container A",
Matricule: "ABC",
From the question it seems that it could be possible to solve it this way.
You can set value of a selected option to property inside of selectChangeHandler()
selectChangeHandler(event) {
this.currentValue = event.target.value;
}
To get it inside of app-heat-local
<div class="modal-body">
<app-heat-local [value]="currentValue"> </app-heat-local>
</div>
To be able to set [value] attribute you need to define #Input() property inside of HeatLocalComponent
You could use #Input() to achieve this.
import {Component, Input} from '#angular/core';
#Component({
selector: 'app-heat-local',
templateUrl: './heat-local.component.html',
styleUrls: ['./heat-local.component.scss']
})
export class HeatLocalComponent {
#Input() value: number;
}
To display the value in heat-local.component.html you can you use interpolation
<h6 class="container-name">{{value}}</h6>
You can read more about component interaction
Update
To receive name instead of index just change value from i which is index to v.Name.
{{v.Name}}
Or you can provide the whole object
<option *ngFor="let v of values;let i = index" [value]="v">
{{v.Name}}
</option>
Becareful with type you specify in here. In previous part there is number type specified so it won't take anything else than number
import {Component, Input} from '#angular/core';
#Component({
selector: 'app-heat-local',
templateUrl: './heat-local.component.html',
styleUrls: ['./heat-local.component.scss']
})
export class HeatLocalComponent {
#Input() value: string // <== Here you can specify the type by TS type
}
string will be used just when value of an option is string, if you want to send whole object then change it to this #Input() value: any or define your own interface
Related
I'm trying to save some data that I display dynamic in the browser.This is my HTML where I iterate trough a list of exam questions dragged from the database and display them dynamic in browser.
<div mat-dialog-content [formGroup]="examform">
<div *ngFor="let exam_question of exam_questions;let i = index">
<mat-label >{{exam_question.questionTitle}}</mat-label><br>
<mat-radio-group aria-label="Image Position">
<mat-radio-button id="{{'examItem1'+i}}" value="1" >{{exam_question.questionItem1}}</mat-radio-button>
<mat-radio-button id="{{'examItem2'+i}}" value="2">{{exam_question.questionItem2}}</mat-radio-button>
<mat-radio-button id="{{'examItem3'+i}}" value="3">{{exam_question.questionItem3}}</mat-radio-button>
<mat-radio-button id="{{'examItem4'+i}}" value="4">{{exam_question.questionItem4}}</mat-radio-button>
</mat-radio-group>
</div>
<div>
<button class="button-course" mat-raised-button color="primary" (click)="submitAnswer()">Submit</button>
How can I use Form from Angular Typescript to save what the user responds to this form? For example what was the answer for the first question, for the second question and so on. I tried to put on every Form Controls and id, but I don t know how to go further.This is the form from Typescript.
import { registerLocaleData } from '#angular/common';
import { Component, OnInit } from '#angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import { Questions } from '../models/questions';
import { SharedService } from '../service/shared.service';
#Component({
selector: 'app-quiz-exam-page',
templateUrl: './quiz-exam-page.component.html',
styleUrls: ['./quiz-exam-page.component.css']
})
export class QuizExamPageComponent implements OnInit {
examID:any;
examform!: FormGroup;
examData: any;
userDetails:any;
examFormArray=new FormArray([new FormControl('',Validators.required)]);
constructor(private formBuilder:FormBuilder,private router:Router,private sharedService:SharedService,private route:ActivatedRoute) { }
exam_questions:Questions[]=[];
ngOnInit(): void {
this.route.queryParams
.subscribe(params => {
this.examID = params['examID'];
}
);
this.examform=this.formBuilder.group({
examTitle:this.formBuilder.array([],Validators.required),
examItem1:this.formBuilder.array([],Validators.required),
examItem2:this.formBuilder.array([],Validators.required),
examItem3:this.formBuilder.array([],Validators.required),
examItem4:this.formBuilder.array([],Validators.required)
});
if(localStorage.getItem('token')==null)
this.router.navigate(['login'])
this.sharedService.getUserProfile().subscribe(res=>{
this.userDetails=res;
this.sharedService.getExamQuestionsByID(this.examID).subscribe(data=>{
this.exam_questions=data;
},err=>{
console.log(err)
});
},(err:any)=>{
console.log(err);
},
);
}
submitAnswer(submitData:any)
{
this.examData = submitData;
console.log(this.examData)
}
}
This is the generated form. And as you can see, I need the answer for every question and after that I click submit, it will save the answer for every question, but I need to know to what question it was the answer, that is why I put the Id in the HTML.
This is my question array. It is an interface:
export interface Questions {
questionID:number;
questionCourseID:number;
questionTitle:string;
questionTopic:string;
questionPoints:string;
questionDifficulty:string;
questionItem1:string;
questionItem2:string;
questionItem3:string;
questionItem4:string;
qustionAnswers:string;
}
To your HTML-File I would add an NgSubmit and also add the type submit to your button. In the ngSubmit you give the value of your form (examForm) to the function (saveForm) in the Typescript-File. Instead I would delete the (click) event on your button.
HTML-File
<div mat-dialog-content [formGroup]="examform" (ngSubmit)="saveForm(examform.value)">
<div *ngFor="let exam_question of exam_questions;let i = index">
<mat-label >{{exam_question.questionTitle}}</mat-label><br>
<mat-radio-group aria-label="Image Position">
<mat-radio-button id="{{'examItem1'+i}}" value="1" >{{exam_question.questionItem1}}</mat-radio-button>
<mat-radio-button id="{{'examItem2'+i}}" value="2">{{exam_question.questionItem2}}</mat-radio-button>
<mat-radio-button id="{{'examItem3'+i}}" value="3">{{exam_question.questionItem3}}</mat-radio-button>
<mat-radio-button id="{{'examItem4'+i}}" value="4">{{exam_question.questionItem4}}</mat-radio-button>
</mat-radio-group>
</div>
<div>
<button type="submit" class="button-course" mat-raised-button color="primary">Submit</button>
If you want, that your button only is pressable if the inputs are valid (for example every required fields are filled out). You can add following code to your button:
<button [disabled]="!examForm?.valid" type="submit" class="button-course" mat-raised-button color="primary">Submit</button>
In your Typescript-File, you should write a function with the same name as you specified in (ngSubmit)="functionName". In my example, the function Name is saveData(). Then you write the value from the Form to a variable with the datatype any.
So your TS-File would look something like:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '#angular/forms';
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
examForm!: FormGroup;
examData: any;
constructor(
private formBuilder: FormBuilder,
) { }
ngOnInit(): void {
this.examForm=this.formBuilder.group({
examTitle:this.formBuilder.array([],Validators.required),
examItem1:this.formBuilder.array([],Validators.required),
examItem2:this.formBuilder.array([],Validators.required),
examItem3:this.formBuilder.array([],Validators.required),
examItem4:this.formBuilder.array([],Validators.required)
});
}
showPreview(submitData: any) {
this.examData = submitData;
console.log(this.examData)
}
}
currently I trying to project a third component in a child component which is projected inside ngFor loop (inside child), but in parent whenever I change or set some property in the projected content using index of query list (ViewChildren('#thirdComponent')) in parent all the child's projected content shows same change. Is there any proper way of doing this.
Is it due to duplicating of select property binding at the place of content projection in child component.Child's projection is done inside a accordion with one or many panels opened at a time.
#Component({
selector: "my-app",
template: `
<child-comp #child>
<ng-container selected>
<some-other-comp #someOtherComp></some-other-comp>
</ng-container>
</child-comp>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit {
h = 0;
i = 1;
j = 2;
k = 3;
#ViewChildren("someOtherComp") otherCompList: QueryList<SomeOtherComponent>;
ngAfterViewInit(): void {
this.otherCompList.toArray()[this.h].prop = this.h;
// below will result in undefined due to QueryList of size 1
// this.otherCompList.toArray()[this.i].prop = this.i;
// this.otherCompList.toArray()[this.j].prop = this.j;
// this.otherCompList.toArray()[this.k].prop = this.k;
}
}
#Component({
selector: "child-comp",
template: `
<div *ngFor="let value of [1, 2, 3]; let i = index">
<!-- if ngIf is removed than only the last projection is diplayed -->
<div *ngIf="i === 0">
<ng-content select="[selected]"> </ng-content>
</div>
</div>
`,
styleUrls: ["./app.component.css"]
})
export class ChildComponent {}
#Component({
selector: "some-other-comp",
template: `
<p>{{ prop }}</p>
`,
styleUrls: ["./app.component.css"]
})
export class SomeOtherComponent {
prop: any;
}
Stackblitz
Utilizing *ngTemplateOutlet and let-variables
We can pass along a template into our child-component, and utilize the #Input() decorator in conjunction with *ngTemplateOutlet to directly access the property from the HTML template in the parent.
Example
First, I've defined an array in my parent component which I want to use as the basis for my loop in my outer-child component.
Parent Component
#Component({
selector: 'parent',
templateUrl: 'parent.component.html',
styleUrls: ['parent.component.scss']
})
export class ParentComponent implements OnInit {
dataItems: { title: string, description: string }[] = [{
title: 'First Element',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet, nihil!'
}...] // remaining items truncated for brevity.
constructor() {
}
ngOnInit(): void {
}
}
This parent component then has a child component, which takes an input of the entire list of items
<child [items]="dataItems"></child>
Child-Component (fist level)
#Component({
selector: 'child',
templateUrl: 'child.component.html',
styleUrls: ['child.component.scss']
})
export class ChildComponent implements OnInit {
#Input() items!: any[];
constructor() {
}
ngOnInit(): void {
}
}
<ng-container *ngFor="let childItem of items">
<projected [item]="childItem">
<ng-template let-item>
<h4>{{item.title}}</h4>
<p>{{item.description}}</p>
</ng-template>
</projected>
</ng-container>
Projected component (sub-child)
#Component({
selector: 'projected',
templateUrl: 'projected.component.html',
styleUrls: ['projected.component.scss']
})
export class ProjectedComponent implements OnInit {
#Input() item: any;
#ContentChild(TemplateRef) templateOutlet!: TemplateRef<any>
constructor() {
}
ngOnInit(): void {
}
}
<ng-container *ngTemplateOutlet="templateOutlet; context: {$implicit: item}"></ng-container>
<ng-content></ng-content>
How does it work
The Parent Component isn't strictly necessary in this relationship, as we aren't projecting content directly from the parent into the ProjectedComponent, I simply chose to define a list of items here to keep a hierarchy similar to your question.
The Child Component
The child component does two things:
Defines a *ngFor loop to loop thru some collection of elements.
Defines a template for how these elements should be utilized in the ProjectedComponent's template.
In the ProjectedComponent we utilize the #ContentChild decorator to select the TemplateRef which we expect to be given via <ng-content>
This template is then put into a container using the *ngTemplateOutlet which also allows us to create a data-binding context to a local variable.
the context: {$implicit: item} tells Angular that any let-* variable defined on the template without any explicit binding should bind to the item property in our component.
Thus, we are able to reference this property in the template at the parent-component level.
Edit
Technically, the context binding is not necessary if you want to define the template directly inside of the child component, as you have a direct reference to the *ngFor template, however it becomes necessary if you want to lift the template out to the ParentComponent level to make the solution more reusable.
You are correct the reason for the bug (changing just the last element) is because when rendered you have multiple elements with the same select value.
A possible solution is to use template reference to pass the desired child component from the top level to the place where you want it to be projected.
Here is a working StackBlitz
import {
AfterViewInit,
Component,
Input,
QueryList,
ViewChildren
} from "#angular/core";
#Component({
selector: "my-app",
template: `
<child-comp #child [templateRef]="templateRef"> </child-comp>
<ng-template #templateRef>
<some-other-comp #someOtherComp></some-other-comp>
</ng-template>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit {
h = 0;
i = 1;
j = 2;
k = 3;
#ViewChildren("someOtherComp") otherCompList: QueryList<SomeOtherComponent>;
ngAfterViewInit(): void {
this.otherCompList.toArray()[this.h].prop = this.h;
this.otherCompList.toArray()[this.i].prop = this.i;
this.otherCompList.toArray()[this.j].prop = this.j;
this.otherCompList.toArray()[this.k].prop = this.k;
}
}
#Component({
selector: "child-comp",
template: `
<div *ngFor="let value of [1, 2, 3, 4]; let i = index">
<!-- if ngIf is removed than only the last projection is diplayed -->
<ng-container *ngTemplateOutlet="templateRef"></ng-container>
</div>
`,
styleUrls: ["./app.component.css"]
})
export class ChildComponent {
#Input() templateRef;
}
#Component({
selector: "some-other-comp",
template: `
<p>{{ prop }}</p>
`,
styleUrls: ["./app.component.css"]
})
export class SomeOtherComponent {
prop: any;
}
Good day developers , im working in this app with angular , and now im trying to once one of the options
get clicked , to show a modal tag .
Basically what i did was create a paralell template equal to the item selected on the dropdown , and over this template using the a tag i set all the logic to show the modal, but guess isn't user friendly cause of couple extra clicks.Trying to set the a tag inside the options also wasn't viable cause the my dropdown didn't work.Here a mock about what i did:
HTML tag
<select [hidden]="!state" name="optionsInc" required [(ngModel)]="optionsInc" (change)="subItemSelected($event)">
<option value="select" [ngValue]="null" [disabled]="true">Select Income</option>
<option *ngFor="let item of allKeysIncomings" label="{{item}}" value="{{item}}"></option>
</select>====>DROPDOWN LIST LOGIC
<p [hidden]="!state"> <a *ngIf="incomeSelected"
href="#"
class="btn btn-primary btn-block"
data-toggle="modal"
data-target="#editItem"
>{{incomeSelected}}</a>
</p>====>PARALELL REFERENCE TO POP THE MODAL UP
<div class="modal fade" id='editItem'>======>MODAL
SOME TAGS AND CODE
</div>
then on my component i did this :
imports...
#Component({
selector: 'app-user-sheet-balance',
templateUrl: './user-sheet-balance.component.html',
styleUrls: ['./user-sheet-balance.component.css'],
})
export class UserSheetBalanceComponent implements OnInit {
allKeysIncomings: any;==>ITERABLE
incomeSelected: string;
constructor(some code) {}
ngOnInit(): void {some code}
async subItemSelected(event) {
SOME CODE
return (
await (this.incomeSelected = event.target.value),
);
}
All this process does the task on activate the modal once i click the tag a, but instead of creating that paralell reference to the dropdown, im wondering if is possible to do it straight from the dropdown in fact.
I have been watching some similar issues on the comunity like
:Open a Modal Using an Option from a Dropdown - Angular 2 + ngx
but doesn't work on my code specifications.
Any updated idea about this ?.Thanks in advance!!!!!!
if you have Component with dialog layout in ModalComponent it should work as follow
import { Injectable } from '#angular/core';
import { MatDialog, MatDialogRef } from '#angular/material/dialog';
import { ModalComponent } from './modal/modal.component';
#Injectable({
providedIn: 'root'
})
export class TestDialogService {
dialogRef: MatDialogRef<ModalComponent, any>;
constructor(public dialog: MatDialog) { }
open() {
if(this.dialogRef) {
this.dialogRef.close();
}
this.dialogRef = this.dialog.open(ModalComponent, {
panelClass: 'app-dialog'
});
}
close() {
if(this.dialogRef) {
this.dialogRef.close();
}
}
}
// html
<mat-form-field>
<mat-label>Favorite car</mat-label>
<select name="optionsInc"
matNativeControl
[(ngModel)]="optionsInc"
(ngModelChange)="onModelChange()">
<option value="select" [value]="null" [disabled]="true">Select Income</option>
<option *ngFor="let item of allKeysIncomings" [label]="item.viewValue"
[value]="item.value"></option>
</select>
</mat-form-field>
// ts
#Component({
selector: 'app-root',
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent {
state = false;
optionsInc = null;
allKeysIncomings = [
{value: 'volvo', viewValue: 'Volvo'},
{value: 'saab', viewValue: 'Saab'},
{value: 'mercedes', viewValue: 'Mercedes'}
];
constructor(
public testDialogService: TestDialogService) {
}
onModelChange() {
this.testDialogService.open();
}
}
example
I'm getting a ExpressionChangedAfterItHasBeenCheckedError when trying to set a value on a click event for a mat-chip
I'm created a stackblitz to see the error in action (Open the console then click two or more chips): https://stackblitz.com/edit/angular-ddapw1?file=app/chips-stacked-example.html
// index.html
<mat-chip-list>
<mat-chip
*ngFor="let chip of availableItems; index as idx"
[selected]="selectedItems.indexOf(idx) > -1"
(click)="select(idx)">
{{chip}}
</mat-chip>
</mat-chip-list>
// index.js
import {Component, ChangeDetectorRef} from '#angular/core';
#Component({
selector: 'chips-stacked-example',
templateUrl: 'chips-stacked-example.html',
styleUrls: ['chips-stacked-example.css'],
})
export class ChipsStackedExample {
constructor(private cdr: ChangeDetectorRef) {}
availableItems = ['foo', 'bar', 'baz'];
selectedItems = [];
select(idx) {
console.log('selecting', idx);
this.selectedItems.push(idx);
//this.cdr.detectChanges()
}
}
You forgot to add the multiple attribute:
<mat-chip-list multiple>
I am actually trying to inject the array and the data inside the array to another component but is constantly getting errors.
My list.component.ts
Here i injected the itemList array from app.component and this component is working just fine. No errors here.
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
import {List} from './list.model'
#Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {
#Input() itemList: List[] = [];
#Output() onItemSelected: EventEmitter<List>;
private currentItem: List;
constructor(){
this.onItemSelected = new EventEmitter();
}
onClick(list: List): void {
this.currentItem = list;
this.onItemSelected.emit(list);
console.log(`clicking list title: ${list.title}`);
}
isSelected(list: List): boolean {
if (!list || !this.currentItem) {
return false;
}
return list.title === this.currentItem.title;
}
ngOnInit() {
}
}
list.component.html
Here i try to inject both the array and then using ngFor i try to inject the single list also.
<div class="ui grid posts">
<app-list-row
[lists]="itemList"
*ngFor="let list of itemList"
[list]="list"
(click)='onClick(list)'
[class.selected]="isSelected(list)">
</app-list-row>
</div>
list-row.component.ts
I am mainly trying to input the array in this component so that i can use the splice method to delete my list. I tried the delete list;method but this says i cannot use delete in strict mode. Therefore i am trying to input the array and use the splice method.
import { Component, OnInit, Input} from '#angular/core';
import {List} from '.././list/list.model';
#Component({
selector: 'app-list-row',
inputs: ['list: List'],
templateUrl: './list-row.component.html',
styleUrls: ['./list-row.component.css'],
host: {'class': 'row'},
})
export class ListRowComponent implements OnInit {
list: List;
#Input() lists: List[];
deletelist(list: List): void {
let index: number = this.lists.indexOf(list);
if (index !== -1) {
this.lists.splice(index, 1);
}
}
ngOnInit() {
}
}
list-row.component.html
In this write a div and use a lable of delete icon and give an event of click with the "deleteList(list)".
<div class="Eight wide column left aligned title">
<div class="value">
<div class = "hello">
<b>
{{ list.title | uppercase }}
</b>
<div style="float: right;" class="ui label">
<i class="delete icon"
(click)="deleteList(list)"
></i>
</div>
</div>
</div>
</div>
These are my codes and i dont know whether i can do the dependency injection of both the array and its single data in the array. If i can, what ways are there to do it. while running in server the console error is
Unhandled Promise rejection: Template parse errors:
Can't bind to 'list' since it isn't a known property of 'app-list-row'.
1. If 'app-list-row' is an Angular component and it has 'list' input, then verify that it is part of this module.
2. If 'app-list-row' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schemas' of this component to suppress this message.
("
[lists]="itemList"
*ngFor="let list of itemList"
[ERROR ->][list]="list"
(click)='onClick(list)'
[class.selected]="isSelected(list)">
"): ListComponent#4:2 ; Zone: <root> ; Task: Promise.then ; Value: SyntaxError {__zone_symbol__error: Error: Template parse errors:
Can't bind to 'list' since it isn't a known property of 'app-list-row'…, _nativeError: ZoneAwareError, __zone_symbol__currentTask: ZoneTask, __zone_symbol__stack: "Error: Template parse errors:↵Can't bind to 'list'…ttp://localhost:4200/polyfills.bundle.js:6060:47)", __zone_symbol__message: "Template parse errors:↵Can't bind to 'list' since …lected]="isSelected(list)">↵"): ListComponent#4:2"} Error: Template parse errors:
Can't bind to 'list' since it isn't a known property of 'app-list-row'.
1. If 'app-list-row' is an Angular component and it has 'list' input, then verify that it is part of this module.
2. If 'app-list-row' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schemas' of this component to suppress this message.
("
[lists]="itemList"
*ngFor="let list of itemList"
[ERROR ->][list]="list"
(click)='onClick(list)'
[class.selected]="isSelected(list)">
Thank you.
Add #Input() to list variable in ListRowComponent class and check if it is working or not and remove inputs from metadata.
import { Component, OnInit, Input} from '#angular/core';
import {List} from '.././list/list.model';
#Component({
selector: 'app-list-row',
templateUrl: './list-row.component.html',
styleUrls: ['./list-row.component.css'],
host: {'class': 'row'},
})
export class ListRowComponent implements OnInit {
#Input() list: List;
#Input() lists: List[];
deletelist(list: List): void {
let index: number = this.lists.indexOf(list);
if (index !== -1) {
this.lists.splice(index, 1);
}
}
ngOnInit() {
}
}
or
Remove :List from inputs as
import { Component, OnInit, Input} from '#angular/core';
import {List} from '.././list/list.model';
#Component({
selector: 'app-list-row',
templateUrl: './list-row.component.html',
inputs :['list']
styleUrls: ['./list-row.component.css'],
host: {'class': 'row'},
})
export class ListRowComponent implements OnInit {
list: List;
#Input() lists: List[];
deletelist(list: List): void {
let index: number = this.lists.indexOf(list);
if (index !== -1) {
this.lists.splice(index, 1);
}
}
ngOnInit() {
}
}
I got the answer. I did not do two input bindings but i created a custom event in the list-row.component and emmited the list to list.Component.
import { Component, Input, Output, EventEmitter} from '#angular/core';
import {List} from '.././list/list.model';
#Component({
selector: 'app-list-row',
templateUrl: './list-row.component.html',
styleUrls: ['./list-row.component.css'],
host: {
'class': 'row'
}
})
export class ListRowComponent {
#Input() list: List;
#Output() deleted = new EventEmitter<List>();
deletedl() {
const listing: List = this.list;
this.deleted.emit(listing);
}
In the template I used the click event to call the deletel() method.
<div class="Eight wide column left aligned title">
<div class="value">
<div class = "hello">
<b>
{{ list.title | uppercase }}
</b>
<div style="float: right;" class="ui label">
<i class="delete icon"
(click)="deletedl()">
</i>
</div>
</div>
</div>
</div>
Then I just called the event in the list.component
list.component.html
<div class="ui grid posts">
<app-list-row
*ngFor="let list of itemList"
[list]="list"
(click)='onClick(list)'
[class.selected]="isSelected(list)"
(deleted)="deletedl($event)">
</app-list-row>
</div>
Then i called a method in list.component to delete the list from the array using Splice method.
list.component
import { Component, Input} from '#angular/core';
import {List} from './list.model';
#Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
})
export class ListComponent {
#Input() itemList: List[] = [];
private currentItem: List;
onClick(list: List): void {
this.currentItem = list;
console.log(`clicking list title: ${list.title}`);
}
isSelected(list: List): boolean {
if (!list || !this.currentItem) {
return false;
}
return list.title === this.currentItem.title;
}
deletedl(list: List) {
console.log(`deleting list title: ${list.title}`);
let index: number = this.itemList.indexOf(list);
if (index !== -1) {
this.itemList.splice(index, 1);
}
}
}
I have learned that if we want to get some input from the parent component than using property binding helps and when we want to run some output from our parent component then event binding is helpful.