0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

検索機能・ページネーション(JavaScript VS Angular)

0
Posted at

検索機能(基本・シンプルバージョン)

JavaScript

フロー

af.jpg

コード

e.htm
<input id="search" />
<ul id="list"></ul>
e.js
const input = document.querySelector('#search');
const list = document.querySelector('#list');

let todos = [
  { id: 1, title: '買い物' },
  { id: 2, title: '勉強' },
  { id: 3, title: '運動' }
];

input.addEventListener('input', () => {
  renderTodos();
});

function renderTodos() {
  list.innerHTML = '';

  // ✅ ① 入力値取得
  const keyword = input.value;

  // ✅ ② filterで抽出
  const filteredTodos = todos.filter(todo =>
    todo.title.includes(keyword)
  );

  // ✅ ③ 描画
  filteredTodos.forEach(todo => {
    const li = document.createElement('li');
    li.textContent = todo.title;
    list.appendChild(li);
  });
}
  • 入力値は DOM(input.value)にある
  • filterしてるのは同じ
  • renderが必要

Angular

コード

e.htm
<input [formControl]="searchControl" />

<ul>
  <li *ngFor="let t of filteredTodos">
    {{ t.title }}
  </li>
</ul>
e.ts
searchControl = new FormControl('');

todos: Todo[] = [
  { id: 1, title: '買い物', completed: false },
  { id: 2, title: '勉強', completed: false },
  { id: 3, title: '運動', completed: false }
];

// ✅ 派生状態
get filteredTodos() {
  const keyword = this.searchControl.value ?? '';
  return this.todos.filter(t =>
    t.title.includes(keyword)
  );
}
  • 入力値も「状態」にする(DOMじゃない)
  • filterはgetterでやる
  • render不要
  • 検索って実はCRUDのDeleteと同じ!ただし元データは変えずに表示だけ変える

検索機能(複数条件付き)

✅ 複数条件検索 =「filterの中で条件を組み合わせる」だけ
✅ Angularでは「状態を複数持って、それをまとめてfilterする」

JavaScript

フロー

IMG_1761.jpeg

IMG_1762.jpeg

コード

e.htm
<input id="search" placeholder="タイトル検索" />
<select id="category">
  <option value="">すべて</option>
  <option value="生活">生活</option>
  <option value="仕事">仕事</option>
</select>

<ul id="list"></ul>
e.js
const input = document.querySelector('#search');
const categorySelect = document.querySelector('#category');
const list = document.querySelector('#list');

let todos = [
  {
    id: 1,
    title: '買い物',
    memo: '牛乳を買う',
    category: '生活',
    completed: false,
    dueDate: new Date('2024-05-01')
  },
  {
    id: 2,
    title: '会議',
    memo: '資料準備',
    category: '仕事',
    completed: false,
    dueDate: new Date('2024-06-01')
  },
  {
    id: 3,
    title: '掃除',
    memo: '部屋を片付ける',
    category: '生活',
    completed: true,
    dueDate: new Date('2024-04-01')
  }
];

// 仮の期間入力(必要ならinput追加)
let from = null;
let to = null;

// 入力が変わるたびに再描画
input.addEventListener('input', renderTodos);
categorySelect.addEventListener('change', renderTodos);

function renderTodos() {
  list.innerHTML = '';

  // ✅ 入力値取得
  const keyword = input.value;
  const category = categorySelect.value;

  const filteredTodos = todos.filter(t => {
  
    // ✅ ① テキスト(タイトル or メモ)
    const matchText =
      !keyword ||
      t.title.includes(keyword) ||
      t.memo?.includes(keyword);

    // ✅ ② カテゴリ
    const matchCategory =
      !category || t.category === category;

    // ✅ ③ 日付
    const matchFrom =
      !from || t.dueDate >= from;

    const matchTo =
      !to || t.dueDate <= to;

    // ✅ 全条件
    return (
      matchText &&
      matchCategory &&
      matchFrom &&
      matchTo
    );
  });

  // ✅ 描画
  filteredTodos.forEach(todo => {
    const li = document.createElement('li');
    li.textContent = todo.title;
    list.appendChild(li);
  });
}
  • filterは
    • true を返した要素だけ残る
    • false を返した要素は消える
  • ので、{}ブロックを書いた場合は必ず自分でreturnしてbooleanを返す必要がある
    ( {}なし=1行なら自動returnなので条件だけ書いて終わりでいい)
E.js
todos.filter(t => {
  t.title.includes(keyword);
});

→こう書いちゃうとreturnがないのでundefined(=false扱い)
👉 全部消える

Angular

コード

e.htm
<input [formControl]="searchControl" placeholder="タイトル検索" />

<select [formControl]="categoryControl">
  <option value="">すべて</option>
  <option value="生活">生活</option>
  <option value="仕事">仕事</option>
</select>

<ul>
  <li *ngFor="let t of filteredTodos">
    {{ t.title }}
  </li>
</ul>
e.ts
get filteredTodos() {
  const keyword = this.searchControl.value ?? '';
  const category = this.categoryControl.value;
  const from = this.fromDate.value;
  const to = this.toDate.value;

  return this.todos.filter(t => {

    // ✅ ① テキスト検索(タイトル or メモ)
    const matchText =
      !keyword ||                  //検索してない→全部OKにするための仕組み
      t.title.includes(keyword) || //タイトルまたは詳細メモに検索文字含まれててもtrue
      t.memo?.includes(keyword);

    // ✅ ② カテゴリ
    //カテゴリ未指定なら全部OK、指定してたら一致するものだけOK
    const matchCategory =
      !category || t.category === category;

    // ✅ ③ 期間
    const matchFrom =
      !from || t.dueDate >= from;

    const matchTo =
      !to || t.dueDate <= to;

    // ✅ 最終判定(全部満たす)
    return (
      matchText &&
      matchCategory &&
      matchFrom &&
      matchTo
    );
  });
}

ページネーション

配列の「一部だけ表示する」

JavaScript

フロー

IMG_1760.jpeg

  • start:(currentPage - 1) * pageSize
    • (currentPage - 1) → 前に何ページあるか
    • pageSize → 1ページに何件あるか
  • つまり、前のページにあったデータ全部スキップする
  • start~endの長さは固定
    →ページの前後はどこまでのデータはスキップしていいか(=start)をずらせば可能

コード

e.js
let currentPage = 1;//今何ページ目か
const pageSize = 3;//1ページに何件表示するか

function renderTodos() {
  list.innerHTML = '';

  // ✅ ① 範囲計算
  const start = (currentPage - 1) * pageSize;
  const end = start + pageSize;

  // ✅ ② sliceで切り出し
  const visibleTodos = todos.slice(start, end);

  // ✅ ③ 描画
  visibleTodos.forEach(todo => {
    const li = document.createElement('li');
    li.textContent = todo.title;
    list.appendChild(li);
  });
}

//ページ移動
function nextPage() {
  currentPage++;
  renderTodos();
}

function prevPage() {
  currentPage--;
  renderTodos();
}

Angular

フロー

  • currentPageを状態として持つ
  • getterでsliceした派生状態を取得→*ngForで表示

コード

E.htm
<ul>
  <li *ngFor="let t of pagedTodos">
    {{ t.title }}
  </li>
</ul>

<button (click)="currentPage = currentPage - 1">前へ</button>
<button (click)="currentPage = currentPage + 1">次へ</button>
e.ts
currentPage = 1;
pageSize = 3;

todos: Todo[] = [
  { id: 1, title: '1' },
  { id: 2, title: '2' },
  { id: 3, title: '3' },
  { id: 4, title: '4' },
  { id: 5, title: '5' }
];

// ✅ 派生状態
get pagedTodos() {
  const start = (this.currentPage - 1) * this.pageSize;
  const end = start + this.pageSize;

  return this.todos.slice(start, end);
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?