Angular material chips removable - javascript

I want to remove the matChip on click of cancel icon
here is my code
<mat-chip-list>
<mat-chip
*ngFor="let user of data.users"
[removable]="true"
[selectable]="true"
(removed)="remove(user.id)">
{{user.name}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
Even though [removable]="true" is set it is not removing the clicked chip
I have been following this docs example

Working example. Please, find the update files from your above link (which is available in your question) as below, while other files remains as same. If you want to check the working code, then try to replace the whole code in respective files of your link with below code to same files.
NOTE: for better readability, I have removed input element with add functionality.
chips-input-example.html
<mat-form-field class="example-chip-list">
<mat-chip-list #chipList aria-label="User selection">
<mat-chip *ngFor="let user of data.users" [selectable]="selectable" [removable]="removable"
(removed)="remove(user.id)">
{{user.name}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</mat-form-field>
chips-input-example.ts
import {Component} from '#angular/core';
interface User {
name: string;
id: number;
}
interface Data {
users: User[];
}
#Component({
selector: 'chips-input-example',
templateUrl: 'chips-input-example.html',
styleUrls: ['chips-input-example.css'],
})
export class ChipsInputExample {
selectable = true;
removable = true;
data: Data = {
users: [
{name: 'User1', id: 0},
{name: 'User2', id: 1},
{name: 'User3', id: 2},
]};
remove(getId: number): void {
this.data.users = [...this.data.users.filter(({id}) => getId !== id)];
}
}
chips-input-example.css
.example-chip-list {
width: 100%;
}

Related

Combobox no showing options

I created a simple reusable component as:
TS
import {Component, Input, OnInit} from '#angular/core';
import {FormControl} from '#angular/forms';
#Component({
selector: 'app-select',
templateUrl: './select.component.html',
styleUrls: ['./select.component.css']
})
export class SelectComponent implements OnInit {
#Input() control: FormControl;
#Input() label: string;
#Input() options: [];
#Input() idAndForAttributes: string;
#Input() customClass: string;
constructor() { }
ngOnInit() {
}
}
HTML
<div class="form-group" [ngClass]="{'invalid': control.invalid && control.touched && control.dirty}">
<label [attr.for]="idAndForAttributes">{{ label }}:</label>
<select class="form-control" [ngClass]="customClass" [formControl]="control" [attr.id]="idAndForAttributes">
<option value="0">- Select -</option>
<option *ngFor="let item of options" [ngValue]="item.id">{{item.description}}</option>
</select>
<ng-container *ngIf="control.dirty && control.touched && control.invalid">
<div *ngIf="control.errors.required || (control.errors.min && control.value == 0)">
<small style="color: #c62828;">
Value is required.
</small>
</div>
</ng-container>
</div>
Now I'm trying to use it in my other html as:
<form [formGroup]="profileActivityForm">
<app-select [control]="profileActivityForm.get('activityType')" [idAndForAttributes]="'type'" [label]="'Type'"
[options]="profileActivityTypes"></app-select>
</form>
Then in TS
profileActivityTypes: string[] = [];
ngOnInit() {
this.profileActivityTypes.push('New')
this.profileActivityTypes.push('Update')
this.profileActivityForm = this.fb.group({
activityType: [0]
});
}
But it is showing invisible options like the following picture:
I think the problem is on the html of the reusable component <option *ngFor="let item of options" [ngValue]="item.id">{{item.description}}</option>
Because it is looking for a description, how can I send the item as a description from the child component?
UPDATE
I tried:
profileActivityTypes: [] = [];
....
let profileActivities = [{ description: 'New' }, { description: 'Update' }]
this.profileActivityTypes.push(profileActivities)
but it is throwing an error on push:
Argument of type '{ description: string; }[]' is not assignable to
parameter of type 'never'
In order to solve this, I changed the assignation of the profileActivities array instead of creating the array and then pushing it. I assign it directly as:
profileActivityTypes = [];
this.profileActivityTypes = [{ id: 1, description: 'New' }, {id: 2, description: 'Update'}]
I hope this works for more people!

How to remove the item which has ```CLOSED``` in ngFor in angular/

TS
#Select(NotificationState.get('onDisplay')) onDisplay$: Observable<Array<Partial<Alert>>>;
HTML
<ng-container *ngFor="let notif of onDisplay$ | async; let i = index">
<span>{{notif.name}}</span>
</ng-container?>
the data is:
[{
name: 'John',
case: 'CLOSED'
},{
name: 'Joshua',
case: 'CLOSED'
},{
name: 'Carl',
case: 'NEW'
},{
name: 'Jen',
case: 'CLOSED'
}]
I'm using observable and what I'm trying to do is to remove the data which has case: 'CLOSED'.
How to remove the item have CLOSED from the array in ngFor?
Demo write custom pipe for this
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'closedPipe'
})
export class CustomPipe implements PipeTransform {
transform(row: any[]): any {
return row.filter(x=>x.case!="CLOSED");
}
}
You could use *ngIf directive to show only properties with certain condition.
<ng-container *ngFor="let notif of onDisplay$ | async; let i = index">
<span *ngIf="notif.case !== 'CLOSED'">{{notif.name}}</span>
</ng-container>

Dynamically nested angular material menu

Please tell me how I can solve the following problem:
I need to implement a dynamically created menu with different nesting levels depending on the data model object. At the moment, using recursion, we managed to create the menu as such, however, there is a problem of assigning the attribute [matMenuTriggerFor] for, directly, the submenu. The problem is that all subsequent submenus in fact refer to the very first, so when you hover over any of the submenus, it causes a "flip" to the original one (example on image: menu, which includes elements: Device, Extension, Queue, Queue member (with submenu elements)). Thus, for a fraction of seconds, I see the other submenu frame (example on image: submenu Grouped list), after which the very first becomes active. Of course, maybe I didn’t do everything right, so I’m turning here. Help me please. Thank you all.
imenu-item.ts
export interface IMenuItem {
name: string | string[];
link: string;
subItems: IMenuItem[];
}
dynamic-menu.service.ts
import {Inject, Injectable} from '#angular/core';
import {APP_CONFIG_ROUTES} from '../../../config/routes/app.config.routes';
import {IAppConfigRoutes} from '../../../config/routes/iapp.config.routes';
import {IMenuItem} from './imenu-item';
import {_} from '#biesbjerg/ngx-translate-extract/dist/utils/utils';
#Injectable({
providedIn: 'root'
})
export class DynamicMenuService {
private readonly appConfig: any;
constructor(#Inject(APP_CONFIG_ROUTES) appConfig: IAppConfigRoutes) {
this.appConfig = appConfig;
}
getMenuItems(): IMenuItem[] {
return [
{
name: _('labels.device'),
link: '/' + this.appConfig.routes.device,
subItems: null
},
{
name: _('labels.extension'),
link: '/' + this.appConfig.routes.extension,
subItems: null
},
{
name: _('labels.queue'),
link: '/' + this.appConfig.routes.queue,
subItems: null
},
{
name: _('labels.queueMember'),
link: null,
subItems: [{
name: _('labels.fullList'),
link: '/' + this.appConfig.routes.queueMember.all,
subItems: null
}, {
name: _('labels.groupedList'),
link: '/' + this.appConfig.routes.queueMember.grouped,
subItems: [{
name: 'subName',
link: 'subLink',
subItems: [{
name: 'subSubName1',
link: 'subSubLink1',
subItems: null
}, {
name: 'subSubName2',
link: 'subSubLink2',
subItems: null
}]
}]
}]
}
];
}
}
dynamic-menu.component.ts
import {Component, Input, OnInit} from '#angular/core';
import {IMenuItem} from './imenu-item';
#Component({
selector: 'app-dynamic-menu',
templateUrl: './dynamic-menu.component.html',
styleUrls: ['./dynamic-menu.component.scss']
})
export class DynamicMenuComponent implements OnInit {
dynamicMenuItemsData: IMenuItem[];
constructor(private dynamicMenuService: DynamicMenuService) {
}
ngOnInit() {
this.dynamicMenuItemsData = this.dynamicMenuService.getMenuItems();
}
}
dynamic-menu.component.html
<div>
<ng-container [ngTemplateOutlet]="recursiveListMenuItems"
[ngTemplateOutletContext]="{$implicit: dynamicMenuItemsData}">
</ng-container>
</div>
<ng-template #recursiveListMenuItems let-listMenuItems>
<div *ngFor="let menuItem of listMenuItems">
<ng-container [ngTemplateOutlet]="menuItem.subItems != null ? subMenuItem : simpleMenuItem"
[ngTemplateOutletContext]="{$implicit: menuItem}">
</ng-container>
</div>
</ng-template>
<ng-template #simpleMenuItem let-menuItemArg>
<a class="mat-button"
mat-menu-item
routerLink="{{menuItemArg.link}}">
<span>{{menuItemArg.name | translate}}</span>
</a>
</ng-template>
<ng-template #subMenuItem let-menuItemArg>
<a class="mat-button"
mat-menu-item
routerLink="{{menuItemArg.link}}"
[matMenuTriggerFor]="subItemsMenu">
<span>{{menuItemArg.name | translate}}</span>
<mat-menu #subItemsMenu="matMenu"
[overlapTrigger]="false">
<ng-container [ngTemplateOutlet]="recursiveListMenuItems"
[ngTemplateOutletContext]="{$implicit: menuItemArg.subItems}">
</ng-container>
</mat-menu>
</a>
</ng-template>
As a result, it turned out, relying on several similar problems with others. The examples from HERE (dynamic nested menu example) and from HERE (the problem with mat-menu hides immediately on opening) helped to figure it out (in the last example it was enough just to update zone.js by npm)
Sorry for the late answer, but maybe you can still find it helpful.
I wrote a little library called ng-action-outlet that is doing that quite neatly in my opinion.
It looks like this:
group: ActionGroup;
constructor(private actionOutlet: ActionOutletFactory) {
this.group = this.actionOutlet.createGroup();
this.group.createButton().setIcon('home').fire$.subscribe(this.callback);
this.group.createButton().setIcon('settings').fire$.subscribe(this.callback);
}
<ng-container *actionOutlet="group"></ng-container>
DEMO: https://stackblitz.com/edit/ng-action-outlet-demo?file=src/app/app.component.ts

Getting select option to show the initial selected option value using Angular

I am having a hard time trying to get the select input to show the initially selected option using Angular. I have tried many options but none have worked so far. Not sure why this is causing me such a headache. Any help would be great, thank you.
The select input shows nothing until I select an option. Would like to dynamically select what option I want selected when app loads.
You can view what I have setup so far with the link below:
https://stackblitz.com/edit/angular-wga92l?file=app%2Fhello.component.ts
Component:
#Component({
selector: 'master-input',
template: `
<form>
<div class="form-group">
<label for="Master-Products">Select Master Product</label>
<select name="pow.name" (ngModelChange)="change($event)" [ngModel]="selectedValue" class="form-control" id="Master-Products">
<option *ngFor="let pow of powers" [ngValue]="pow.id" [selected]="pow.id == 3">{{pow.name}}</option>
</select>
</div>
</form>
`,
styleUrls: ['./master-input.component.scss']
})
export class MasterInputComponent {
#Output() hasChanged: EventEmitter<number> = new EventEmitter();
powers: any[] = [{ id: 1, name: 'Bead Ruptor Elite' }, { id: 2, name: 'Bead Ruptor 12' }, { id: 3, name: 'Bead Ruptor 96' }];
selectedValue: string = 'Bead Ruptor 96';
change(value: number) {
this.hasChanged.emit(value);
}
}
just Add ngOnInit function
powers: any[] = [ 'power1', 'power2', 'power3' ];
ngOnInit(){
this.selectedValue ='power3';
}
change(value:string) {
this.hasChanged.emit(value)
}
It was tested in your fiddle.
Please see working image

How does angular2 distinguish between different <ng-template>?

I am writing a table component, usually the contents of the table are fixed, but some columns may require component users to create a column template, I am prepared to pass the to pass the custom column template, but I encountered a problem, I did not know which columns I needed to customize when I passed the column data.
Now I have simplified the code as follows:
#Component({
selector: 'example',
template: `
<ng-container *ngFor="let item of data">
<div *ngIf="!item.value">
<ng-template [ngTemplateOutlet]="item.ref" [ngOutletContext]="{}"></ng-template>
</div>
<div *ngIf="item.value">{{item.value}}</div>
</ng-container>
`
})
export class DatatableComponent{
#Input() data: object[];
#ContentChildren(TemplateRef) get refs(val: TemplateRef<any>) {
// How to map refs here to map above
}
}
// use it:
#Component({
selector: 'app',
template: `
<example [data]="data">
<ng-template name="test1">test1</ng-template>
<ng-template name="test2">test2</ng-template>
</example>
`
})
export class DatatableComponent{
// I know that you can get references here
// But this hard code is too cumbersome,
// I was wondering if there was any other better way
public data: object[] = [
{name: 'test1'},
{name: 'test2'},
{name: 'test3', value: 'test3'}
]
}

Categories