Как передать значение формы из одного компонента в список в другом компоненте с помощью сервисов angular?

Я пытался разработать проект списка дел. У меня есть четыре компонента: Daily, Item-List, Item и Add-task

Ежедневный компонент содержит форму и список, в котором отображаются значения из формы. Далее я собираюсь создать форму в модальном диалоговом окне (новый отдельный компонент) и добавить ее значение в список в ежедневном компоненте.

Ниже приведены коды:

Daily.service.ts

Этот служебный код используется для получения значения из формы и добавления его в список.

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { DailyTask } from './models';

@Injectable({ providedIn: 'root' })
export class DailyService {

private _dailies$ = new BehaviorSubject<DailyTask[]>([]); 
public getDailies(): DailyTask[] {
return this._dailies$.getValue();
}

public setDailies(data: DailyTask[]): void {
 this._dailies$.next(data);
}

public getDailiesObservable(): Observable<DailyTask[]> {
return this._dailies$.asObservable();
}

public createTask(newTask: string): void{

console.info( "check");

  const dailyTask: DailyTask = { task: newTask, type: 'DAILY' };
  this.setDailies([dailyTask, ...this.getDailies()])
 }
}

Суточная.компонент.Ц

export class DailyComponent implements OnInit {
  public dailyList$: Observable<DailyTask[]> | null = null;

  constructor(private _dailyService: DailyService) {}

  ngOnInit(): void {
    this.dailyList$ = this._dailyService.getDailiesObservable();
  }

  public addDaily(name: string) {
     this._dailyService.createTask(name);
  }
 }

Daily.component.html

 <mat-card>
   <h1>Daily</h1>
    <app-item-list
      [type] = "'DAILY'"
      [initialData$] = "dailyList$"
      [onAddItem] = "addDaily.bind(this)"
    ></app-item-list>
 </mat-card>

Item-List.component.html

<div>
 <mat-form-field appearance = "outline">
 <input
  matInput
  placeholder = "Add a Task"
  (keyup.enter) = "addTask()"
  autocomplete = "off"
  [formControl] = "nameControl"/>
 </mat-form-field>
</div>

<ng-container *ngIf = "filteredData$ | async as data">

<app-item
  [value] = "value"
  *ngFor = "let value of data; index as index"
  (inputDataChange) = "removeTask(data, index)"
>
</app-item>
</ng-container>

Item-list.component.ts

export class ItemListComponent implements OnInit {
   
   nameControl = new FormControl('');
   @Input() public type: ItemType | null = null;
   @Input() public onAddItem: Function | null = null;
   
   constructor(private _homeService: HomeService) {}
   ngOnInit(): void {}

   addTask() {
     if (this.onAddItem) {
        this.onAddItem(this.nameControl.value);
        this.nameControl.reset();
   }
 }

item.component.html

<div class = "displayTask">
  <div class = "displayvalue" [ngClass] = "{ 'line-through': value.task }">
     {{ value.task | uppercase }}
  </div>
</div>

item.component.ts

export class ItemComponent implements OnInit {
  @Input()
   value: any;
  constructor() {}
  ngOnInit(): void {}
 }

Приведенный выше набор кодов работает отлично, ниже код для нового компонента task-dailog

задача-dailog.html

<div mat-dialog-title class = "dailogHeader">
   <h1 >Create Daily</h1>
</div>

<div mat-dialog-content>
    <div class = "dialogContent">
      <p>Task</p>
    <mat-form-field appearance = "outline">
    <input
        matInput
        placeholder = "Add a new Task"
        autocomplete = "off"
        (keyup.enter) = "addDailogTask()"
        [formControl] = "nameControl"
    />
    </mat-form-field>
    </div>
</div>

задача-dailog.component.ts

export class TaskDialogComponent implements OnInit {
  nameControl = new FormControl('');

  constructor(
    public dialogRef: MatDialogRef<TaskDialogComponent>,
    private _dailyService: DailyService,
  ) {}

  ngOnInit(): void {}

  onNoClick(): void {
    this.dialogRef.close();
  }

  addDailogTask(){
    const value$ =   this.nameControl.value;
    this.nameControl.reset();
    console.info(value$);
  }
 }

Здесь, в task-dialog.component.ts, у меня есть функция для получения значения из формы, но я застрял здесь и не знаю, что делать дальше. Я хотел бы узнать, как отправить это значение формы из TaskDialogComponent в список внутри DailyComponent.

Вот также Stackblitz для проекта.

Может кто-то помочь мне с этим . Я относительно новичок в angular и был бы очень признателен за помощь. Заранее спасибо!.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
86
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Сначала вам нужно указать тип значения формы. По умолчанию form.value может быть возвращен как any, который не соответствует createTask функции, для которой требуется только string

Решение

addDailogTask() {
  const value$ = this.nameControl.value as string;
  ...
}

Проверьте эту работу: https://stackblitz.com/edit/github-pdhugz-sbinrb?file=src%2Fapp%2Fadd-task-btn%2Fadd-task-btn.component.ts

  1. Были некоторые проблемы с task-dialog.component.html. По сути, вы хотите двусторонне связать поле ввода «Задача». Вы должны указать [mat-dialog-close] = "task", чтобы явно отправить данные из диалога в dialogRef в AddTaskBtnComponent

  2. После того, как диалог подключен правильно... вы можете получить значение из диалога в методе afterClosed().subscribe.

    добавить-задачу-btn.component.ts:

    @Component({
     selector: 'app-add-task-btn',
     templateUrl: './add-task-btn.component.html',
     styleUrls: ['./add-task-btn.component.scss'],
    })
    export class AddTaskBtnComponent implements OnInit {
    
    
      ...
    
     openDialog(): void {
    
       const dialogRef = this.dialog.open(TaskDialogComponent, {
       width: '500px',
       height: '500px',
       });
    
       dialogRef.afterClosed().subscribe((task) => {
         if (task) {
           this.dailyService.createTask(task);
         } 
         console.info('The dialog was closed');
       });
      }
     }
    }
    
  3. MatDialogModule не был импортирован в TaskDialogModule


Я вижу некоторые проблемы с вашим кодом и его структурой.

Советы:

  1. Вы хотите структурировать свой код так же, как структурирован ваш пользовательский интерфейс. Так будет легче работать. Например:

    src
      app
      L home
        L shared
          L components
             L item-list
                 L components
                    L item 
        L components
           L profile-banner
           L searchbar
           L add-task-btn
           L daily
             L components
             L services
               L daily.service.ts
             L ... 
           L todo
           L habits 
        L services
        L models 
        L home.component.ts
        L home.component.scss
        L home.component.html
    
  2. Не знаю, почему вы решили поместить каждый компонент в отдельный модуль. Что технически не нужно, страница входа может быть в одном модуле, а все остальное, что есть в домашнем компоненте, может быть в другом модуле. Таким образом, вы можете лениво загружать HomeModule.

  3. Когда у вас есть глубоко вложенный компонент. Я бы порекомендовал использовать библиотеку управления состоянием (я использую ngxs), с ней намного проще работать, поэтому вам не нужно передавать значения через декоратор @input. Кроме того, это сделает ваш код более читабельным.

Другие вопросы по теме