Angular Material mat-chips not setting to be removable - html

Problem Statement
My problem is that when I am using Angular Material's mat-chip, it seems it cannot be set as removable even though I set it to true.
Code
<mat-form-field>
<input matInput [matChipInputFor]="chipList" (matChipInputTokenEnd)="addOption($event)"
type="number" maxlength="4" placeholder="Enter an amount here">
</mat-form-field>
<mat-chip-list>
<mat-chip #chipList *ngFor="let option of options" [removable]="true"
(removed)="removeOption(option)">{{option}}
</mat-chip>
</mat-chip-list>
RemoveOption Method
removeOption(option: String) {
const index = this.options.indexOf(option);
if (index >= 0) {
this.options.splice(index, 1);
}
}
Explanation of Code
As you can see, I have set [removable] to true and (removed) with a removeOption method. These things do not work for some strange reason.
I copied the example from here: https://material.angular.io/components/chips/examples, the section with the example is named: "Chips with Input"
Actual Output
The chips show no little remove button on the right:
Expected Output
The chips with a little remove button on the right:

You have to add the mat-icon to trigger the removal. In the material example you have:
<mat-chip
*ngFor="let fruit of fruits"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(fruit)">
{{fruit}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
This contains the action to trigger matChipRemove inside the mat-icon.
Link for demo: https://stackblitz.com/angular/mjygopomxvq?file=src%2Fapp%2Fchips-autocomplete-example.html

you are missing the icon tag.
<mat-chip-list>
<mat-chip #chipList *ngFor="let option of options" [removable]="true"
(removed)="removeOption(option)">{{option}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>

You're not able to see the icon because the section <mat-icon matChipRemove>cancel</mat-icon> is missing from the code.
Your code should look like this:
<mat-chip-list>
<mat-chip #chipList *ngFor="let option of options" [removable]="true"
(removed)="removeOption(option)">{{option}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>

Noticed that if the mat-icon or any other element that does matChipRemove has style "pointer-events: none;" then click on the mat-icon (X) doesn't remove the chip. The chip still can be removed by the keyboard backspace button. Solution - set "pointer-events: auto;"

Related

Prevent Mat-chip from adding row after selection

I am trying to prevent the mat-chip module from automatically adding a row after one chip has been selected. The max chip count is 1, so I disable the input after the user selects an item from the dropdown. But, it still adds a row beneath it as if they can type more. How can I prevent that?
<mat-chip-list #chipList aria-label="Fruit selection" >
<mat-chip
*ngFor="let item of selected; let i = index"
[selectable]="!disabled"
[removable]="!disabled"
(removed)="remove(i)">
{{item[filterProperty]}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input
[maxLength]="maxLength"
[value]="optionBaseValue"
[placeholder]="label" #chipsInput
[disabled]="(selected.length === maxCount) || inEditMode === false"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(focus)="autoInputValue($event)"
(focusout)="resetAutoInputValue($event)"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="itemSelected($event)" (onBlur)="itemSelected($event)">
<mat-option *ngFor="let item of filteredItems | async " [value]="item">
<div > {{item[filterProperty]}}</div>
</mat-option>
</mat-autocomplete>
Thank you!!
You could use something like:
<input [hidden]="selected.length === 1"
Note that you can change the conditional however you like.

How to access formarray value in the typescript file of angular

I'm unable to access the form array value in typescript file. I'm getting it as blank array
This is my html code
<mat-form-field class="example-full-width" >
<mat-label>Locations </mat-label>
<mat-chip-list #chipList aria-label="Fruit selection">
<mat-chip
*ngFor="let loca of locationlist"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(loca)">
{{loca.locationName}}
<mat-icon matChipRemove (click)="remove(loca)">cancel</mat-icon>
</mat-chip>
<input
placeholder="Locations"
#fruitInput
formArrayName="locationctrl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let locc of locations " [value]="locc"> {{locc.locationName}} </mat-option>
</mat-autocomplete>
</mat-form-field>
i need a method that should return a array value but i'm getting the blank array value
To get a formarray value or any value from HTML to .ts file is very easy. What you need to do is,
write this code in your HTML file:-
{{log(formarray)}} // or any value you want to log in console.
and in your .ts file, you can write this function:-
log(value) {
console.log(value);
}

how to add mat select in Angular input

I'm finding away to add mat select on my input field but some reason when I click on the arrow, it's not working and not showing me all the list.
I have autocomplete and usually when a user start typing it show all the list to select but I'm trying add mat-select also so that user can just click on the arrow and select from the list without having to type something first.
I've followed below stackblitz example ( checkbox is not needed for mine) but mine is little bit different and I also have text input and auto complete so I'm not sure why I can't type anymore in my input with current code and also the drop down list are not showing when I click the arrow.
any suggestion or help will be really apprecaited.
https://stackblitz.com/edit/angular-material-v9-mat-select-with-mat-chip-list?file=src%2Fapp%2Fselect-multiple-example.html
<mat-form-field class="form" appearance="fill">
<mat-label>Search or Select a Super Tag</mat-label>
<mat-select [formControl]="superTags" multiple>
<mat-select-trigger>
<mat-chip-list #chipList>
<div>
<mat-chip *ngFor="let superTag of superTags" [selectable]="selectable" [removable]="removable"
(removed)="remove(superTag)">
<img class="super-icon" src="/assets/images/icons/super-tag-icon.svg">
{{superTag.tag}}
<mat-icon matChipRemove *ngIf="removable" matTooltip="Remove a super tag">cancel</mat-icon>
</mat-chip>
</div>
<div>
<input matInput #input [(ngModel)]="tagIn" [formControl]="tagCtrl" [matAutocomplete]="auto" [matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" (matChipInputTokenEnd)="addTag()">
</div>
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngIf="isLoading" class="is-Loading">
<mat-spinner diameter="20"></mat-spinner>
</mat-option>
<ng-container *ngIf="!isLoading">
<mat-option *ngFor="let tag of filteredSuperTags | async" [value]="tag">
{{tag}}
</mat-option>
</ng-container>
</mat-autocomplete>
</mat-select-trigger>
</mat-select>
</mat-form-field>
In this case I would not use the combination of chip list and autocomplete.
I think, what you really need, is the autocomplete with options which contain checkboxes for the multiselect. Try to do, somethihg like this.
<mat-form-field class="example-full-width">
<input type="text" placeholder="Select Users" aria-label="Select Users" matInput [matAutocomplete]="auto" [formControl]="userControl">
<mat-hint>Enter text to find users by name</mat-hint>
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngFor="let user of filteredUsers | async" [value]="selectedUsers">
<div (click)="optionClicked($event, user)">
<mat-checkbox [checked]="user.selected" (change)="toggleSelection(user)" (click)="$event.stopPropagation()">
{{ user.firstname }} {{ user.lastname }}
</mat-checkbox>
</div>
</mat-option>
</mat-autocomplete>
Full example:
https://stackblitz.com/edit/angular-sx79hu?embed=1&file=app/multiselect-autocomplete-example.html

how to place text input beside of chips in Angular

I'm trying to make the mat form field that can show tags, input and drop down like the design below but I'm not sure how to achieves that so can anybody help me out. I've tried different methods for a few hour now but still can't find a way to make it work. will be really appreciated if somebody can give me suggestion or help.
I'm just trying to place the text input to be always beside of Chips (maybe expand like what I have right now if user put a lot of chips) and also have drop down options (icon) on the side like the design below.
<mat-chip-list *ngIf="editMode">
<mat-form-field class="form" appearance="fill">
<!--show Tags-->
<ng-container *ngFor="let chip of chips" class="add-tag-chip" (click)="displayTagInput()">
<mat-chip [selectable]="selectable" [removable]="removable" (removed)="removeTags(chip)">
{{chip.tag}}
<mat-icon matChipRemove *ngIf="chip.pending !== true && removable" matTooltip="Remove a tag">cancel</mat-icon>
<mat-spinner *ngIf="chip.pending === true" [diameter]="16" mode="indeterminate"></mat-spinner>
</mat-chip>
</ng-container>
<!--Text Input (supposed to be on the side of Tags)-->
<input matInput [(ngModel)]="tagIn" [matAutocomplete]="auto" placeholder="New Tag" (keyup.enter)="addTag()" />
<!--For Drop Down List-->
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let tag of filteredTags | async" [value]="tag">
{{tag}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</mat-chip-list>
This is the design I'm trying to do
This is what I have right now
Why don't you use it as it is represented in the documentation ? I also found this stackblitz that is exactly what you want. Here is the html code :
<mat-form-field class="demo-chip-list">
<mat-chip-list #chipList>
<mat-chip
*ngFor="let fruit of fruits"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(fruit)">
{{fruit}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input
placeholder="New fruit..."
#fruitInput
[formControl]="fruitCtrl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"
/>
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let fruit of filteredFruits | async" [value]="fruit">
{{ fruit }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
Note that there is no ng-container ( they don't seems mandatory in your code) and the mat-form-field tag wrap the whole thing. In your code you have it as a child of mat-chip-list.
[Edit]: I got it. Here is the code :
.css :
/* ::ng-deep needed to only target your component (it's deprecated but have not replacement for the moment) */
.your-component ::ng-deep .mat-form-field-infix {
display: flex !important
}
/* Change the placeholder to stick to the same position as if your input is focused, not really good */
.your-component ::ng-deep.mat-form-field-label {
transform: translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px) !important;
}
.html:
<mat-chip-list>
<mat-form-field>
<!-- ng-container is now a span -->
<span *ngFor="let fruit of fruits" (click)="displayTagInput()">
<mat-chip [selectable]="selectable" [removable]="removable" (removed)="removeTags(chip)">
{{fruit}}
<mat-icon matChipRemove matTooltip="Remove a tag">cancel
</mat-icon>
</mat-chip>
</span>
<input matInput [(ngModel)]="tagIn" [matAutocomplete]="auto2" placeholder="New Tag..." (keyup.enter)="addTag()" />
<mat-autocomplete #auto2="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let fruit of filteredFruits | async" [value]="fruit">
{{ fruit }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</mat-chip-list>
Here is the demo ons tackblitz. Note that it does not work perfectly. I had to force the shrink effect of the placeholder with the css (I think it's because mat-form-field is inside mat-chip-list).
Also, since i removed some come to make it clearer, you will have to test it with your own code, chip remove methods etc.
Hope it helps :)

Mat-chip-list call function when option added/changed

I'm using a mat-chip-list and I have certain functionality that occurs when an option is removed. However, I'd also like something to happen when an option is added or in fact a call that happens when an option is added or removed (ie the contents change)
I've tried (click)="testMethod()" and (selectionChnaged)="testMethod()" but neither seems to work.
<mat-form-field class="btn-div" *ngIf="showSectors">
<mat-chip-list #chipList>
<mat-chip *ngFor="let sector of chosenSectors" [removable]="true" (removed)="removeSector(sector)">
{{ sector.service_code + ": " + sector.service }}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input placeholder="Sectors" #sectorInput [formControl]="sectorCtrl" [matAutocomplete]="auto"
[matChipInputFor]="chipList" [matChipInputAddOnBlur]="true">
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let sector of filteredSectors | async" [value]="sector" matTooltip={{sector.commodity}}
[matTooltipPosition]="'after'" [matTooltipShowDelay]="500">
{{ sector.service_code + ": " + sector.service }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
The (click) functionality works when it is inside the mat-form-field but this isn't suitable as I will eventually be passing the value of the field through to the method I want to call and this value isn't set upon clicking of the mat-form-field.