简体   繁体   English

如何使用 2 个搜索栏过滤相同的数据 - ReactJS

[英]How to to filter the same data with 2 search bars - ReactJS

I want some help here.我在这里需要一些帮助。 I want to filter the same data with 2 search bars, one to filter the names and the other one to filter the array of notes.我想用 2 个搜索栏过滤相同的数据,一个用于过滤名称,另一个用于过滤笔记数组。

IF: I am only filtering by names => get Results (length > 0) OR length = 0.如果:我只按名称过滤 => 获取结果(长度 > 0)或长度 = 0。
ELSE IF: I am only filtering by names => get Results (length > 0) OR length = 0. ELSE IF:我只按名称过滤 => 获取结果(长度 > 0)或长度 = 0。
ELSE IF: I am filtering by both of them names & notes => get Results (length > 0) OR length = 0. ELSE IF:我正在按他们两个名称和注释进行过滤 => 得到结果(长度 > 0)或长度 = 0。
ELSE: Do nothing.其他什么都不做。

The interface looks like this:界面如下所示:

interface StudentInterface {
    email: string;
    firstName: string;
    notes: string [];
    id: string;
    lastName: string;
}

Below is the screen-shot of the 2 search bars.以下是 2 个搜索栏的屏幕截图。

Any help is appreciated.任何帮助表示赞赏。 Thanks in advance.提前致谢。

在此处输入图像描述

Here's an example of how to utilize client-side dual filters:以下是如何使用客户端双重过滤器的示例:

编辑双重过滤学生名单


Code (with notes):代码(带注释):

App.tsx应用程序.tsx

import { ChangeEvent, FormEvent, ReactElement, useState } from "react";
import { studentData, Student } from "./studentsData";
import "./styles.css";

type Filters = {
  name: string;
  note: string;
};

const initialFilters = {
  name: "",
  note: ""
};

export default function App(): ReactElement {
  const [students, setStudents] = useState<Array<Student>>(studentData);
  const [filters, setFilters] = useState<Filters>(initialFilters);
  const { name, note } = filters;

  // on input change, update the corresponding field (event.target.name) with the field's value (event.target.value)
  const handleFilterChange = (event: ChangeEvent<HTMLInputElement>): void => {
    setFilters((prevState) => ({
      ...prevState,
      [event.target.name]: event.target.value
    }));
  };

  // on form reset, reset field filters and students state
  const handleResetFilters = (): void => {
    setFilters(initialFilters);
    setStudents(studentData);
  };

  // on form submit, filter data according to field filters values
  const handleSubmit = (event: FormEvent): void => {
    event.preventDefault();

    // prevent an empty form from filtering data
    if (!name && !note) {
      alert("Please fill out at least one filter before submitting the form!");
      return;
    }

    const filteredStudents = studentData.filter((student) => {
      // combine the student's first and last name
      // and check if the student's name contains the "name" filter value
      const containsStudentName = `${student.firstName} ${student.lastName}`
        .toLowerCase()
        .includes(name.toLowerCase());

      // check if the student's notes contain a partial match to the "note" filter value
      const containsStudentNote = student.notes.some(
        (studentNote) => studentNote.indexOf(note) > 0
      );

      // true = keep, false = discard
      if (name && note) {
        // if name and note filters are used, return the result of the above boolean values
        return containsStudentName && containsStudentNote;
      } else if (
        (name && containsStudentName) ||
        (note && containsStudentNote)
      ) {
        // else if name and containsStudentName are a match or if note and containsStudentNote are a match, keep record
        return true;
      } else {
        // else, discard record
        return false;
      }
    });

    setStudents(filteredStudents);
  };

  return (
    <main className="app">
      <h1>Filter Student Form</h1>
      <form onSubmit={handleSubmit}>
        <input
          className="filter"
          name="name"
          onChange={handleFilterChange}
          placeholder="Filter by student name..."
          value={name}
        />
        <input
          className="filter"
          name="note"
          onChange={handleFilterChange}
          placeholder="Filter by student note..."
          value={note}
        />
        <div className="btn-container">
          <button
            className="btn btn-danger"
            type="button"
            onClick={handleResetFilters}
          >
            Reset
          </button>
          <button className="btn btn-primary" type="submit">
            Submit
          </button>
        </div>
      </form>
      <h1>Student List</h1>
      {students.length > 0 ? (
        students.map(({ id, email, firstName, lastName, notes }) => (
          <div className="card" key={id}>
            <h3>
              {firstName} {lastName} ({email})
            </h3>
            <p>{notes.join(", ")}</p>
          </div>
        ))
      ) : (
        <div>No results were found matching those filters...</div>
      )}
    </main>
  );
}

studentsData.ts学生数据.ts

export type Student = {
  email: string;
  firstName: string;
  notes: string[];
  id: string;
  lastName: string;
};

export const studentData: Array<Student> = [
  {
    id: "1",
    email: "ervinh@hotmail.com",
    firstName: "Ervin",
    lastName: "Howell",
    notes: [
      "I manage enterprise e-tailers",
      "I aggregate real-time technologies"
    ]
  },
  {
    id: "2",
    email: "patricia@kory.org",
    firstName: "Patricia",
    lastName: "Lebsack",
    notes: ["I revolutionize enterprise end-to-end systems"]
  },
  {
    id: "3",
    email: "lg@gmail.com",
    firstName: "Leanne",
    lastName: "Graham",
    notes: ["I transition cutting-edge web services"]
  },
  {
    id: "4",
    email: "denSchu@jasper.info",
    firstName: "Dennis",
    lastName: "Schulist",
    notes: ["I synergize scalable supply-chains"]
  },
  {
    id: "5",
    email: "kw@aol.com",
    firstName: "Kurtis",
    lastName: "Weissnat",
    notes: ["I enable strategic applications"]
  },
  {
    id: "6",
    email: "patricia@patriciareichert.com",
    firstName: "Patricia",
    lastName: "Reichert",
    notes: ["I target end-to-end models"]
  }
];

index.tsx索引.tsx

import { render } from "react-dom";
import App from "./App";

render(<App />, document.getElementById("root"));

styles.css styles.css

body,
html {
  height: 100vh;
  width: 100%;
  margin: 0;
  padding: 0;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

::-webkit-scrollbar {
  display: none;
}

.app {
  font-family: sans-serif;
  text-align: center;
  margin: 0 auto;
  width: 600px;
  padding: 20px;
}

.filter {
  width: 100%;
  height: 40px;
  padding: 0 10px;
  background: #fff;
  color: #666;
  border: 1px solid #e5e5e5;
  transition: all 0.2s ease-in-out;
  margin: 5px 0;
}

.btn {
  cursor: pointer;
  margin-right: 20px;
  border: 1px solid transparent;
  text-transform: none;
  border-radius: 4px;
  display: inline-block;
  padding: 0 30px;
  font-size: 14px;
  line-height: 38px;
  text-align: center;
  text-transform: uppercase;
  transition: all 0.2s ease-in-out;
}

.btn-container {
  margin: 20px 0;
}

.btn-primary {
  background-color: #1e87f0;
  color: #fff;
}

.btn-primary:hover {
  background-color: #0f7ae5;
}

.btn-danger {
  background-color: #f0506e;
  color: #fff;
}

.btn-danger:hover {
  background-color: #ee395b;
}

.card {
  background-color: rgb(255, 255, 255);
  padding: 10px;
  margin: 10px;
  color: rgb(18, 18, 18);
  transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
  border-radius: 4px;
  box-shadow: rgba(0, 0, 0, 0.2) 0px 3px 3px -2px,
    rgba(0, 0, 0, 0.14) 0px 3px 4px 0px, rgba(0, 0, 0, 0.12) 0px 1px 8px 0px;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM