Установите связь между родственными компонентами в Angular 11

Опубликовано: 26 Августа, 2022

В этой статье мы увидим, как мы можем передавать данные между одноуровневыми компонентами на клиентской машине.

В Angular мы делим нашу веб-страницу на несколько компонентов, и связь между этими компонентами образует древовидную структуру. Компонент может иметь родителя и несколько дочерних элементов. Тем не менее, у него также могут быть братья и сестры. В некоторых ситуациях нам нужно передавать данные между этими независимыми компонентами. Передача данных проста, и это делает наш код чище и читабельнее при работе над большим проектом.

Предварительные требования: NPM должен быть предварительно установлен.

Чтобы понять, как это работает, посмотрите на схему ниже:

  • В случае пользовательского события мы можем выдать данные из одного компонента.
  • Эти данные будут отправлены в родительский компонент.
  • Родительский компонент может в дальнейшем передавать эти данные в виде входных данных другому дочернему компоненту.
  • Это односторонняя передача, но мы можем использовать ее и в другом направлении, чтобы создать двусторонний канал связи.

В Angular мы можем добиться этого, используя встроенные функции:

  • Декоратор @Output помогает передавать данные через объект EventEmitter<T>. Мы увидим его работу на примере.
  • Родительский компонент будет захватывать данные как переменную $event. Он может использовать его в методе или передать другим способом.
  • Наконец, декоратор @Input() использует переменную, и любой ввод через родителя будет сохранен в этой переменной.

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

Сначала настроим среду:

  • Установите угловой клиент. Запустите от имени администратора или используйте sudo в случае ошибок прав доступа.
npm i -g @angular/cli
  • Когда angular CLI установлен, запустите новый проект, используя следующую команду:
ng new <project-name>
  • Теперь протестируйте его, используя:
ng serve -o
  • Если к целевой странице angular можно получить доступ по адресу http://localhost:4200, установка прошла успешно. Прежде чем двигаться дальше, очистите содержимое app.component.html.
  • После этого сгенерируйте два новых компонента:
ng generate component search
ng generate component table
  • Вы увидите два каталога «поиск» и «таблица» в папке приложения. В каждом из них будет по 4 новых файла.

Давайте создадим наш компонент поиска и создадим из него событие. Сначала в search.component.html напишите следующий код:

HTML




<br><br>
<div>
    <label for="search">Enter the text</label>
    <br>
    <br>
    <input type="text" id="search" placeholder="type some words" 
           (keyup)="emit(keyword.value);" #keyword>
</div>

В приведенном выше коде есть простое поле ввода, которое использует функцию emit() при возникновении события keyup. Мы будем использовать это, чтобы передать ключевое слово родительскому компоненту. Давайте определим этот метод и событие в search.component.ts :

Javascript




import { Component, EventEmitter, OnInit, Output } 
        from "@angular/core";
  
@Component({
  selector: "app-search",
  templateUrl: "./search.component.html",
  styleUrls: ["./search.component.css"]
})
export class SearchComponent implements OnInit {
  
  constructor() { }
  ngOnInit(): void {
  }
  @Output() emitter:EventEmitter<string>
       = new EventEmitter<string>();
  
  emit(keyword){
      this.emitter.emit(keyword);
  }
}

Объект-эмиттер типа «строка» будет испускать указанный параметр в своем методе emit(). При событии keyup метод emit() выполняет метод emit() объекта-эмиттера.

Теперь давайте заполним код в table.component.ts :

Javascript




import { Component, DoCheck, Input, OnInit } from "@angular/core";
  
@Component({
  selector: "app-table",
  templateUrl: "./table.component.html",
  styleUrls: ["./table.component.css"]
})
export class TableComponent implements OnInit, DoCheck {
  data = [
    {name:"Liam", age:"20", post: "Marketing Coordinator"},
    {name:"Noah", age:"25" , post:"Medical Assistant"},
    {name:"Oliver", age:"22", post:"Web Designer"},
    {name:"William", age:"20", post:"Dog Trainer"},
    {name:"Bill", age: "22", post:"President of Sales"},
    {name:"James", age: "19", post:"Project Manager"},
  ];
  items = [];
  constructor() { }
  @Input() keyword:string;
  
  ngOnInit(): void {
    this.refresh();
  }
  
  ngDoCheck(){
    this.refresh();
  }
  
  refresh(){
    this.items = [];
    this.data.forEach(
      item => {
        if(item.name.search(this.keyword) != -1
         || item.age.search(this.keyword) != -1 
         || item.post.search(this.keyword) != -1) {
          this.items.push(item)
        }
      }
    
  }
}

В этом примере мы объявили объект данных, который представляет собой некоторые статические данные для нашей таблицы.

  • Переменная «ключевое слово» определяется как вход для этого компонента с помощью декоратора @Input().
  • Мы объявили метод refresh(), который заполняет список элементов, используя соответствие содержимого в любом из полей с переменной «ключевое слово».
  • Мы вызвали этот метод в методах ngDoCheck и ngOnInit (обратите внимание, что мы должны реализовать для них интерфейс). Метод ngDoCheck называется обнаружением после изменения в приложении. Следовательно, всякий раз, когда ключевое слово изменяется в родительском, этот метод заменяет список.
  • Мы покажем этот список на table.component.html, используя следующий код:

HTML




<p *ngIf="!items.length">No results found</p>
  
<table class="table" *ngIf="items.length">
    <thead >
        <td>Name</td>
        <td>Age</td>
        <td>Post</td>
    </thead>
    <br>
    <tr *ngFor="let item of items">
        <td>{{item.name}}</td>
        <td>{{item.age}}</td>
        <td>{{item.post}}</td>
    </tr>
</table>

Вышеприведенный код отображает таблицу, присутствующую в массиве «items». Теперь давайте напишем код для родительского компонента app.component.ts :

Javascript




import { Component } from "@angular/core";
  
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  title = "GeeksForGeeks";
  keyword = "";
  send(keyword){
    this.keyword = keyword;
  }
}

В приведенном выше коде:

  • Мы объявили переменную ключевого слова.
  • Метод send() принимает ключевое слово в качестве параметра и устанавливает его в переменную класса.
  • Мы будем использовать переменную класса «ключевое слово» в качестве входных данных для табличного компонента.
  • Событие, сгенерированное компонентом поиска, будет обрабатываться методом send().
  • См. приведенный ниже код для app.component.html :

HTML




<div>
  <app-search (emitter)="send($event)"></app-search>
</div>
<hr>
  
<div>
  <app-table [keyword]="keyword"></app-table>
</div>

В этом коде:

  • Переменная «$event» представляет данные, выдаваемые компонентом поиска.
  • Переменная ключевого слова табличного компонента передается как [ключевое слово].

Теперь сохраните все файлы и протестируйте код, используя:

ng serve -o

На http://localhost:4200 мы можем увидеть результат.

Выход: