Я пытался разработать проект списка дел. У меня есть четыре компонента: 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 и был бы очень признателен за помощь. Заранее спасибо!.
Сначала вам нужно указать тип значения формы. По умолчанию 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
Были некоторые проблемы с task-dialog.component.html
. По сути, вы хотите двусторонне связать поле ввода «Задача». Вы должны указать [mat-dialog-close] = "task"
, чтобы явно отправить данные из диалога в dialogRef
в AddTaskBtnComponent
После того, как диалог подключен правильно... вы можете получить значение из диалога в методе 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');
});
}
}
}
MatDialogModule
не был импортирован в TaskDialogModule
Я вижу некоторые проблемы с вашим кодом и его структурой.
Советы:
Вы хотите структурировать свой код так же, как структурирован ваш пользовательский интерфейс. Так будет легче работать. Например:
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
Не знаю, почему вы решили поместить каждый компонент в отдельный модуль. Что технически не нужно, страница входа может быть в одном модуле, а все остальное, что есть в домашнем компоненте, может быть в другом модуле. Таким образом, вы можете лениво загружать HomeModule
.
Когда у вас есть глубоко вложенный компонент. Я бы порекомендовал использовать библиотеку управления состоянием (я использую ngxs), с ней намного проще работать, поэтому вам не нужно передавать значения через декоратор @input
. Кроме того, это сделает ваш код более читабельным.