[英]Add ONLY the selected chip
My goal is to add a chip that has been selected.我的目标是添加已选择的芯片。 If there is no option, a chip should be added by the value which has been typed.
如果没有选项,则应按已键入的值添加筹码。
All <mat-option>
values are from my database.所有
<mat-option>
值都来自我的数据库。 My problem is that if I type something and there is an option selected, it will add 2 chips.我的问题是,如果我输入一些内容并选择了一个选项,它将添加 2 个筹码。
Example例子
The value JavaScript exists in my database and it will be displayed as <mat-option>
.我的数据库中存在值JavaScript ,它将显示为
<mat-option>
。 If I type Java (it could also be J ), JavaScript will be selected.如果我输入Java (也可以是J ),将选择JavaScript 。 So what I want is to add the chip JavaScript only (since it is selected) but not both of them.
所以我想要的是只添加芯片JavaScript (因为它被选中)但不是两者都添加。 This is how it looks like:
这是它的样子:
HTML HTML
<mat-grid-tile [formGroup]="this.primaryFormGroup">
<mat-chip-list #chipList>
<mat-chip *ngFor="let currentTechnology of currentTechnologies" [selectable]="selectable"
[removable]="removable" (removed)="remove(currentTechnology)">
{{currentTechnology.name}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<label>
<input #techInput
(keyup)="onKeyUp($event)"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"
placeholder="Technologies"
name="technologies"
formControlName="technologies"
>
</label>
</mat-chip-list>
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let data of technologies" [value]="data.technology">
<span matBadge="{{data.counter}}" matBadgeOverlap="false">{{data.technology}} </span>
</mat-option>
</mat-autocomplete>
</mat-grid-tile>
TypeScript TypeScript
import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';
import {COMMA, ENTER, SPACE, TAB} from '@angular/cdk/keycodes';
import {MatAutocomplete, MatAutocompleteSelectedEvent, MatChipInputEvent} from '@angular/material';
import {TechnologiesService} from './technologies.service';
import {SelectionService} from '../sections/selection.service';
import {FormBuilder, FormControl, NgForm, Validators} from '@angular/forms';
import countries from '../../../assets/json/countries.json';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.sass']
})
export class FormComponent implements OnInit {
@ViewChild('techInput', {static: false}) techInput: ElementRef<HTMLInputElement>;
@ViewChild('auto', {static: false}) matAutocomplete: MatAutocomplete;
@ViewChild('customForm', {static: true}) customForm: NgForm;
@Input() section: string;
separatorKeysCodes = [COMMA, SPACE, TAB, ENTER];
selectable = false;
removable = true;
addOnBlur = true;
technologies = [];
setTechnologies;
currentTechnologies = [];
minDate = new Date();
countries = countries;
// Primary form group
primaryFormGroup = this.fb.group({
title: '',
description: '',
gender: '',
city: '',
country: '',
language: '',
highestEducation: '',
dateOfBirth: '',
workload: '',
typeOfTask: '',
hourlyRate: '',
paymentTime: '',
minPrice: '',
maxPrice: '',
deadlineFrom: '',
deadlineUntil: '',
technologies: '',
milestones: [false, Validators.requiredTrue]
});
// Important form group
importantFormGroup = this.fb.group({
gender: [false, Validators.requiredTrue],
city: [false, Validators.requiredTrue],
country: [false, Validators.requiredTrue],
language: [false, Validators.requiredTrue],
highestEducation: [false, Validators.requiredTrue],
dateOfBirth: [false, Validators.requiredTrue],
workload: [false, Validators.requiredTrue],
hourlyRate: [false, Validators.requiredTrue],
paymentTime: [false, Validators.requiredTrue]
});
constructor(private technologiesService: TechnologiesService, private selection: SelectionService, private fb: FormBuilder) {}
// Form Control
required = new FormControl('', Validators.required);
hourlyRate = new FormControl('', Validators.max(200));
ngOnInit() {
// Set the min date
this.minDate = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), this.minDate.getDate());
// Modify the form object
this.primaryFormGroup.valueChanges.subscribe(inputFields => {
if (inputFields) {
// Change technologies
if (inputFields.technologies) {
// inputFields.technologies = Array.from(this.setTechnologies);
// delete inputFields.technologies;
}
// Change type-of-task
const typeOfTask = inputFields.typeOfTask;
if (typeOfTask) {
if (typeOfTask === 'project') {
inputFields.project = 1;
} else if (typeOfTask === 'feature') {
inputFields.feature = 1;
} else if (typeOfTask === 'bugfix') {
inputFields.bugfix = 1;
} else if (typeOfTask === 'other') {
inputFields.other = 1;
}
delete inputFields.typeOfTask;
}
// Change tech
const inputEntries = Object.entries(inputFields).filter(([key, value]) => value);
// console.log('result:', inputEntries);
}
});
}
// Get the current section
getSelectedSection() {
return this.selection.getSection();
}
// On Key up, show technologies
onKeyUp(event: any): void {
if (event.target.value.trim().length > 0) {
this.technologiesService.getTechnologies(event.target.value)
.subscribe(data => {
if (JSON.stringify(this.technologies) !== JSON.stringify(data)) {
this.technologies = data;
}
});
}
}
// On enter, add technology
onEnter(evt: any) {
if (evt.source.selected) {
this.add(evt.source);
evt.source.value = '';
}
}
// Add technologies
add(event: MatChipInputEvent): void {
if (!this.matAutocomplete.isOpen) {
console.log('add');
const input = event.input;
const value = event.value;
if ((value || '').trim()) {
// E.g., { "name": "Java" }
this.currentTechnologies.push({name: value.trim()});
// Set technologies without keys
if (this.setTechnologies) {
this.setTechnologies.add(value);
} else {
this.setTechnologies = new Set();
this.setTechnologies.add(value);
}
}
// Reset the input value
if (input) {
event.input.value = '';
}
}
}
// Select the autocomplete
selected(event: MatAutocompleteSelectedEvent): void {
console.log('select');
if (!JSON.stringify(this.currentTechnologies).includes(`{"name":"${this.techInput.nativeElement.value.trim()}"`)) {
this.currentTechnologies.push({name: this.techInput.nativeElement.value.trim()});
this.techInput.nativeElement.value = '';
}
}
// Remove technology
remove(tech: any): void {
const index = this.currentTechnologies.indexOf(tech);
if (index >= 0) {
this.currentTechnologies.splice(index, 1);
}
}
}
I think the main problem is that if I select an option, both functions ( selected()
and add()
) will be executed.我认为主要问题是,如果我选择 select 一个选项,两个函数(
selected()
和add()
)都将被执行。 As you see, I have already tried it with this.matAutocomplete.isOpen
but the return is ALWAYS false.如您所见,我已经使用
this.matAutocomplete.isOpen
进行了尝试,但返回总是错误的。
I have found an example on Stackblitz , which works exactly the way I want it.我在Stackblitz上找到了一个示例,它完全按照我想要的方式工作。 But I have spent more than 10 hours to fix my code to make it work the same but I have NO IDEA what exactly is wrong with my code.
但是我花了 10 多个小时来修复我的代码以使其工作相同,但我不知道我的代码到底有什么问题。
If you have an idea what it could be, I would REALLY appreciate it!如果您知道它可能是什么,我将非常感激!
Updates更新
this.currentTechnologies.push({name: value.trim()});
this.currentTechnologies.push({name: value.trim()});
(in function add()
), ONLY the selected option will be added, which is good but if I type anything else which is not in my array technologies
, that will not be added. add()
中),只会添加选定的选项,这很好,但如果我键入不在我的数组technologies
中的任何其他内容,则不会添加。this.currentTechnologies.push({name: this.techInput.nativeElement.value.trim()});
this.currentTechnologies.push({name: this.techInput.nativeElement.value.trim()});
(in function selected()
), only the value that I have typed will be added. selected()
中),只会添加我输入的值。Try to remove the addOnBlur option or set it to false in yout ts file.尝试删除 addOnBlur 选项或在 yout ts 文件中将其设置为 false。 That worked for me!
这对我有用!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.