Ajay Singh
Ajay Singh

Reputation: 171

Angular Material Chips to be displayed under the input box

I am using Angular Material to create chips entered in the input field. So, the current default behaviour as given in documentation examples is to display chips inside the input box. I don't want to show those chips inside my input field what I wanna do is when user enters anything, the chip should be created under the input field(not inside the input field). You can just help me with any example link.

Upvotes: 4

Views: 13647

Answers (3)

Ajay Singh
Ajay Singh

Reputation: 171

I used an input component that would take inputs and then add it to any array. Then I passed this array to chips component that would display chips.

Template that calls keyDown and blur to add chips on these two events. Called another component that displays chips passing the array of chips.

<form [formGroup]="form">
    <mat-form-field appearance="outline">
        <mat-label>Key Skills</mat-label>
        <input matInput placeholder="Skills" (keydown)="onAddSkills($event)" (blur)="onBlurMethod()" formControlName="keySkills" name="keySkills">
    </mat-form-field>
    <div class="chip-list">
        <chip-list [skills]="skills"></chip-list>
    </div>
</form>

The component for this template

import {Component} from '@angular/core';
import { FormGroup, FormControl, FormBuilder } from '@angular/forms';

export interface Skills {
  name: string;
}

@Component({
  selector: 'key-skills',
  templateUrl: 'key-skills.component.html',
  styleUrls: ['key-skills.component.scss'],
})
export class KeySkillsComponent {
    skills: Skills[] = [];
    private form: FormGroup; 
    constructor(private fb: FormBuilder) { 
        this.form = this.fb.group({
            "keySkills": new FormControl()
    });
    }

  onAddSkills(event) {
    if (event.key === "Enter" || event.key===",") {
        this.addSkillsToArray(this.form.value['keySkills']);
    }
  }

  onBlurMethod() {
            this.addSkillsToArray(this.form.value['keySkills'])
  }

  addSkillsToArray(skill) {
    if ((skill || '').trim()) {
        this.skills.push({name: skill.trim()});
            }
        this.form.reset();
    event.preventDefault();
  }
}

Chip List template

<mat-chip-list>
    <mat-chip *ngFor="let skill of skills">
        {{skill.name}}
        <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
    </mat-chip>
</mat-chip-list>

and Component

import {Component, Input} from '@angular/core';

@Component({
  selector: 'chip-list',
  templateUrl: 'chip-list.component.html',
  styleUrls: ['chip-list.component.scss'],
})
export class ChipListComponent {
    @Input() skills;
}

Easy peasy. The results of all this is: enter image description here

Upvotes: 2

nick
nick

Reputation: 2018

If you look at the Angular Material Chip example you can pull the input out of mat-form-field

Update: If you reorder the input element in the example from the docs then the chips appear below the input (where the user enters text) but still part of the component:

<mat-form-field class="example-chip-list">
  <input placeholder="New fruit..."
        [matChipInputFor]="chipList"
        [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
        [matChipInputAddOnBlur]="addOnBlur"
        (matChipInputTokenEnd)="add($event)">

  <mat-chip-list #chipList>
    <mat-chip *ngFor="let fruit of fruits" [selectable]="selectable"
            [removable]="removable" (removed)="remove(fruit)">
      {{fruit.name}}
      <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
    </mat-chip>
  </mat-chip-list>
</mat-form-field>

That might not get you exactly where you envisioned but I think it gets at the spirit of the solution you're looking for.

See this StackBlitz I tweaked from the example.

Upvotes: 6

The easiest way to implement that is playing with CSS position property.

But it's actually better to use flexbox: https://codepen.io/avreddy/pen/ppzraz

.md-chips { 
  display: flex;
  flex-wrap: wrap;
} 
.md-chips md-chip{
  order: 2;
}
.md-chips .md-chip-input-container {
  order: 1;
  width: 100%;
}

Upvotes: 1

Related Questions