Добавьте ТОЛЬКО выбранный чип - PullRequest
0 голосов
/ 01 ноября 2019

Моя цель - добавить выбранный чип. Если нет никакой опции, чип должен быть добавлен к введенному значению.

Все значения <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, но возвращение ВСЕГДА ложно.

Я нашел пример на Stackblitz , который работает именно так, как я хочу. Но я потратил более 10 часов, чтобы исправить свой код, чтобы он работал так же, но у меня НЕТ ИДЕИ, что именно не так с моим кодом.

Если у вас есть идея, что это может быть, я бы ДЕЙСТВИТЕЛЬНОцените это!

Обновления

  • Если удалить this.currentTechnologies.push({name: value.trim()}); (в функции add()), будет добавлена ​​ТОЛЬКО выбранная опция, что хорошоно если я введу что-то еще, чего нет в моем массиве technologies, это не будет добавлено.
  • Если я удалю this.currentTechnologies.push({name: this.techInput.nativeElement.value.trim()}); (в функции selected()), будет введено только значение, которое я набралбыть добавленным.
...