how to place text input beside of chips in Angular - html

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 :)

Related

How to add an Input into an option of a dropdown list

I have a dropdown list of technology with a mat-select element and I would like to add for each option an input to specify the technology's version.
My dropdown list :
Close :
Open :
The problem is that when I click in the input to write the version, it selects the option without editing the input.
Here is my code :
<mat-form-field appearance="fill">
<mat-label>Choisissez les technologies parmi cette liste</mat-label>
<mat-select formControlName="listeTechnologies" multiple>
<mat-option *ngFor="let item of listeDeroulanteTechnologies" [value]="item.code1">
{{ item.valeur1}}
<input type="text" placeholder="Version"/>
</mat-option>
</mat-select>
</mat-form-field>
Stackblitz link : https://stackblitz.com/edit/angular-ivy-lednqy?file=src/app/app.component.html
Do you have any idea ?
By using the exemple here I've found the solution :
<mat-form-field appearance="fill">
<mat-label>Choisissez les technologies parmi cette liste</mat-label>
<mat-select formControlName="listeTechnologies" multiple>
<ng-container *ngFor="let item of listeDeroulanteTechnologies ; let i = index" class="containerTechnologie" formArrayName="listeVersion">
<mat-option class="optionTechnologie" [value]="item.code1">{{ item.valeur1}}</mat-option>
<mat-form-field appearance="standard" class="versionTechnologie">
<input placeholder="Version {{item.valeur1}}" matInput [formControlName]="i"/>
</mat-form-field> <br/>
</ng-container>
</mat-select>
</mat-form-field>
CSS Classes :
.containerTechnologie{
display: flex;
justify-content: space-between;
}
.optionTechnologie{
display:inline-flex;
width:100%;
}
.versionTechnologie{
width:25%;
position:absolute;
right:35%;
margin-top:-15px;
}
Result :

How to change style of MatChipList and MatAutoComplete input?

I'm trying to create something similar to the picture below :
the problem is I can't change the height or the width of the input form. I've looked for similar questions but none of them answer my questions.
here is my html code :
<mat-form-field class="example-chip-list" appearance="fill">
<mat-label>Favorite Fruits</mat-label>
<mat-chip-list #chipList aria-label="Fruit selection">
<mat-chip
*ngFor="let fruit of fruits"
(removed)="remove(fruit)">
{{fruit}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip>
<input
placeholder="New fruit..."
#fruitInput
[formControl]="fruitCtrl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
(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>

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 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

Angular Material mat-chips not setting to be removable

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;"