Find with user-friendly input/label removal function (Ionic 2)

I have embarked on creating a recipe application where users can search for recipes by ingredients. I want to enhance the functionality of the search feature so that when users press the spacebar to enter the next input, it appears as a label below with an option to deselect by clicking on an X.

Currently, my search feature looks like this:

However, I envision it looking like this with labels underneath:

Since this is for an Ionic 2 app, I am wondering if anyone has come across a similar implementation or tutorial? Any guidance or assistance would be greatly appreciated.

UPDATE: I recently noticed that the "Tags" section at the bottom of Stack Overflow pages showcases the exact feature I am aiming for in my app

Answer №1

If you're searching for a solution similar to this, check out the plunker example here. Although there's room for enhancements and additional validations, the demo should meet your requirements.

The code is quite simple and focuses on these key sections:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  ...
  ...
})
export class HomePage {

  public myForm: FormGroup;
  public tags: Array<string>;

  constructor(public formBuilder: FormBuilder) {
    this.tags = ['tag1', 'tag2', 'tag3'];
    this.myForm = this.formBuilder.group({
      tags: ['']
    });

    // Implementing async validation for username
    this.myForm.get('tags')
        .valueChanges
        .subscribe((value: string) => {
          if(value.indexOf(' ') > -1) {
            let newTag = value.split(' ')[0];
            console.log(newTag);
            if(newTag) {
              this.tags.push(newTag);
              this.myForm.get('tags').setValue('');
            }
          }
        });
  }

  public deleteTag(tagName: string) {
    // Find tag index
    let index = this.tags.indexOf(tagName);

    // Remove tag from list
    this.tags.splice(index, 1);
  }
}

In the view section:

<ion-header>
  <ion-navbar>
    <ion-title>HomePage</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>      
  <form [formGroup]="myForm">
    <ion-item>
      <ion-input formControlName="tags" type="text"></ion-input>
    </ion-item>
  </form>

  <div class="tag-container">
    <span class="tag" *ngFor="let tag of tags">
      {{ tag }}
      <ion-icon name="close" (click)="deleteTag(tag)"></ion-icon>
    </span>
  </div>
</ion-content>

Lastly, don't forget about the CSS styling:

.tag-container {
  border: 1px solid #ccc;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  padding: 10px;
  margin: 10px;
}

.tag {
  display: inline-block;
  background-color: #5bc0de;
  color: #fff;
  margin: 5px 5px;
  padding: 2px 5px;
}

Answer №2

To tackle this issue, I recommend focusing on the data model perspective. The key is to break down your objective to its essence: for every input event in your search field,

  1. Convert the search term into an array of words
  2. Remove the last word from the array to create a list of labels
  3. Assign the last word as the value for your input field

Consider the following scenario with a component structured like:

@Component({
  .....
  template: `
    <input [formControl]="searchControl" (input)="onSearchInput(input.value)" />
    <label *ngFor="let label of labels">{{ label }} </label>
  `
})
export class SearchComponent {
  searchControl = new FormControl('');
  labels: string[] = [];

  onSearchInput(searchValue) {
    let newSearchValues: string[] = searchValue.split(' ');
    if (newSearchValues.length > 1) {
      this.labels.push(newSearchValues[0]);
      this.searchControl.setValue(newSearchValues[1]);
    }
  }
}

Utilize @angular/forms package's FormControl to bind your search input for dynamic value updates and leverage the FormsModule functionalities. Monitor input events on your search field to dynamically manage labels and input values.

This foundation can serve as a starting point. Additional logic may be necessary to handle special cases or implement debouncing for improved functionality. Stay adaptable and explore further enhancements as needed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm curious if there's a method to ensure that the content within a mat-card stays responsive

So I'm working with this mat-card: <mat-card> <mat-card-content> <div *ngFor="let siteSource of siteSources | paginate: { itemsPerPage: 5, currentPage: page};"> <site-details [site]='siteSource'></s ...

What is the proper way to validate a property name against its corresponding value?

Here is the structure of my User class: export class User { public id: number; //Basic information public email: string; public firstName: string; public lastName: string; //Permissions public canHangSocks: boolean; p ...

The parseFloat function only considers numbers before the decimal point and disregards

I need my function to properly format a number or string into a decimal number with X amount of digits after the decimal point. The issue I'm facing is that when I pass 3.0004 to my function, it returns 3. After reviewing the documentation, I realized ...

Is it possible to implement GrailsApplicationCommand within an angular project using the gradle wrapper?

Within my Grails angular project, I have a unique GrailsApplicationCommand that I need to execute in the context of the server project. Currently, I am able to successfully run this command from the working directory of the server using the grails CLI: g ...

What is preventing this from being a function?

It appears that the authenticationProvider is missing for some reason. @autoinject() export class ProviderManager implements AuthenticationManager { constructor( private container: Container ){ } public authenticate( creds: Credentials ): Promis ...

I am in need of a customized 'container' template that will display MyComponent based on a specific condition known as 'externalCondition'. MyComponent includes the usage of a Form and formValidation functionalities

container.html <div ngIf="externalCondition"> <!--Initially this is false. Later became true --!> <my-component #MyComponentElem > </my-component> <button [disabled]= "!myComponentElemRef.myDetailsF ...

Jest: A runtime error occurred because the property being accessed is undefined

Currently, I am testing my React class which includes the import statement import dotnetify from "dotnetify";. While this works without any issues, Jest is reporting that dotnetify is undefined. Interestingly, when I switch the import to const do ...

transformation of categorized unions in software development

Experimenting with routing-controllers and its built-in class-transformer feature, I tried creating an interface for executing a search query based on either a location id or location coordinate. My aim was to utilize a discriminated union as a body parame ...

Definition files (.d.ts) for JavaScript modules

I'm currently working on creating Typescript typings for the link2aws package in order to incorporate it into my Angular project. Despite generating a .d.ts file, I am still encountering the following error message: TypeError: (new link2aws__WEBPACK_I ...

What is the process for integrating ion-tabs with IonicVueRouter within an Ionic (vue.js) application?

My Project Idea I have a vision to create an innovative exercise warm-up application. The app will be divided into two main sections: a workout tab and a settings tab. The user journey will start with selecting a workout plan, then choosing specific exerc ...

What might be the reason why the custom markers on the HERE map are not displaying in Angular?

I'm having trouble displaying custom icons on HERE maps. Despite not receiving any errors, the icons are not showing up as expected. I have created a demo at the following link for reference: https://stackblitz.com/edit/angular-ivy-zp8fy5?file=src%2Fa ...

Nx repository encountering module resolution issue

Hey there (and happy new year!), Recently, I utilized a template for a monorepo provided by our organization to migrate an Angular project into the monorepo. Before running npm i, I made sure to add all necessary dependencies. However, after restarting VS ...

Tips for moving between multiple router outlets on a page?

My search has lasted for half a day, but I am still unable to find a solution that works. Here are the routes I currently have: app-routing.module.ts const routes: Routes = [ { path: '', redirectTo: 'feature2', pathMatch ...

Can data from an Angular app be accessed by an external JavaScript code within the same project?

I've been thinking about a theoretical scenario that luckily I haven't encountered yet. Imagine I have an Angular Project compiled in My PROJECT FOLDER. <br/> Inside this PROJECT FOLDER, there's another JAVASCRIPT FILE external to ...

Facing difficulty in accessing mongoose schema static method in TypeScript

I am currently facing an issue where I have a method called "findByToken()" defined in the model and implemented as a static method in the userSchema. However, in another part of my application, I am unable to access the method using: User.findByToken(tok ...

show the stored value inside the useRef variable

One of my challenges involves a variable const prediction = useRef<any>(null); A button triggers a function that updates the variable's value: function showResult() { classifier.current.classify(capture, (result) => { ...

When Typescript calls the toString method on a Function, it produces unexpected characters like "path_1, (0, promises.writeFile)"

I'm currently attempting to convert a function into a string for transmission to a worker thread for execution. However, when imported code is included, the resulting string contains strange characters. import { HttpStatus } from '@nestjs/common& ...

Exploring the Features of PrimeNG Table Component in Angular 8

After attempting to implement p-table (PrimeNG table) in my Angular project and importing all necessary dependencies and modules using the CLI, I encountered the following error: ERROR: The target entry-point "primeng/table" has missing dependencies: - @ ...

The angular core module is displaying an inaccurate peer dependency warning regarding zone.js

Encountered this error message when trying to update my Angular version: @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e88b879a8da8d9d8c6d9c6dd">[email protected]</a>" has an incorrect peer dependency ...

Tips for properly implementing an enum in TypeScript when using the React useState hook

What's the correct way to utilize my useState hook? I have this enum type: export enum Status { PENDING = 'pending', SUCCESS = 'success', ERROR = 'error', } And the useState hook: const [isValid, setIsValid] = use ...