仅添加所选芯片

时间:2019-11-01 15:02:44

标签: javascript angular typescript angular-material

我的目标是添加已选择的芯片。如果没有选择,则应在键入的值后加上一个筹码。

所有<mat-option>值都来自我的数据库。我的问题是,如果我键入内容并且选择了一个选项,它将增加2个筹码。

示例

JavaScript 存在于我的数据库中,它将显示为<mat-option>。如果输入 Java (也可以是 J ),则将选择 JavaScript 。所以我想要的是仅添加芯片 JavaScript (因为已选择),而不是全部添加。看起来像这样:

enter image description here

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

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);
    }
  }

}

我认为主要的问题是,如果我选择一个选项,则将同时执行两个功能(selected()add())。如您所见,我已经用this.matAutocomplete.isOpen进行过尝试,但是返回结果始终为false。

我在Stackblitz上找到了一个示例,该示例完全按照我想要的方式工作。但是我花了十多个小时来修复我的代码,以使其能够正常工作,但是我不知道我的代码到底有什么问题。

如果您有什么想法,我将不胜感激!

更新

  • 如果我删除this.currentTechnologies.push({name: value.trim()}); (在功能add()中,仅会添加所选的选项,这很好 但是如果我键入数组technologies中没有的其他任何内容, 不会被添加。
  • 如果我删除了this.currentTechnologies.push({name: this.techInput.nativeElement.value.trim()});(在功能selected()中),则只会添加我键入的值。

1 个答案:

答案 0 :(得分:1)

尝试删除addOnBlur选项或在文件中将其设置为false。那对我有用!